1

I have a complex xml structure that looks like :

  <Items>
      <Item>
          <ItemTexts>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
              <ItemTextsLine>1</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
              <ItemTextsLine>2</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
              <ItemTextsLine>3</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
              <ItemTextsLine>4</ItemTextsLine>
            </ItemText>
          </ItemTexts>
         </Item>
    <Item>
          <ItemTexts>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
              <ItemTextsLine>1</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
              <ItemTextsLine>2</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
              <ItemTextsLine>3</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
              <ItemTextsLine>4</ItemTextsLine>
            </ItemText>
          </ItemTexts>
         </Item>
<Item>
          <ItemTexts>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
              <ItemTextsLine>1</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type1</ItemTextsType>
              <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
              <ItemTextsLine>2</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
              <ItemTextsLine>3</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
              <ItemTextsLine>4</ItemTextsLine>
            </ItemText>
          </ItemTexts>
         </Item>
    <Item>
          <ItemTexts>
            <ItemText>
              <ItemTextsType>type3</ItemTextsType>
              <ItemTextsTypeDesc>description31</ItemTextsTypeDesc>
              <ItemTextsLine>1</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type3</ItemTextsType>
              <ItemTextsTypeDesc>description32</ItemTextsTypeDesc>
              <ItemTextsLine>2</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
              <ItemTextsLine>3</ItemTextsLine>
            </ItemText>
            <ItemText>
              <ItemTextsType>type2</ItemTextsType>
              <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
              <ItemTextsLine>4</ItemTextsLine>
            </ItemText>
          </ItemTexts>
         </Item>
    </Items>

I run with xsl on each Item like :

<xsl:for-each select="Items/Item">

I need an example of how to group <ItemText> by <ItemTextsType> individually for each <Item> so the outcome will be like :

For first <Item> in this example :

type1

description11

description12

type2

description21

description22

For second Item in this example :

type3

description31

description32

type2

description21

description22

of course I will arrange the outcome in a table like :

<table width="100%" border="1" style="display: block;">
        <tbody>
            <tr>
                <td id="SelectedRowLinkageContents">
                    <table width="100%" dir="ltr">
                        <tbody>
                            <tr style="background-color: #507CD1; text-align: center">
                                <td colspan="3" style="font: bold; color: white">
                                    Item1
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type1
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription11
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription12
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type2
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription21
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription22
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription23
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <table width="100%" dir="ltr">
                        <tbody>
                            <tr style="background-color: #507CD1; text-align: center">
                                <td colspan="3" style="font: bold; color: white">
                                    Item2
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type1
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription11
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription12
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type2
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription21
                                </td>
                            </tr>

                            <tr>
                                <td>
                                    desription23
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <table width="100%" dir="ltr">
                        <tbody>
                            <tr style="background-color: #507CD1; text-align: center">
                                <td colspan="3" style="font: bold; color: white">
                                    Item3
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type1
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription11
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription12
                                </td>
                            </tr>
                            <tr>
                                <td style="height: 35px; font: bold; color: #507CD1;">
                                    type2
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    desription21
                                </td>
                            </tr>

                            <tr>
                                <td>
                                    desription23
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
        </tbody>
    </table>

The point is that there is separate grouping for each <Item> into it's own <table> and inside that <table> there is groupping by <ItemTextsType>

I have tried something like

<xsl:key name="item-texts-type" match="ItemText" use="ItemTextsType" />


<xsl:for-each select="ItemTexts/ItemText[count(. | key('item-texts-type', ItemTextsType)[1]) = 1]">

                        <xsl:sort select="ItemTextsType" />
                        <tr>
                          <td style ="height:35px;font: bold; color:#507CD1;">
                            <xsl:value-of select="ItemTextsType" />
                          </td>
                        </tr>

                        <xsl:for-each select="key('item-texts-type', ItemTextsType)">
                          <tr>
                            <td>
                               <xsl:value-of select="ItemTextsTypeDesc" />
                            </td>
                          </tr>
                        </xsl:for-each>


                      </xsl:for-each>

but it only work on non repetitive nodes (if there were only one <Item>it would work fine). I can't change xml because it comes from customer .

Please help me , I need it ASAP .

Thank you !!!!

Polina F.
  • 629
  • 13
  • 32

1 Answers1

3

It's still difficult to tell what the desired solution is due to some discrepancies - for instance, your input XML has 4 <Item> elements, but your desired output only takes 3 of them into account. Additionally, several descriptions in your desired output do not match up with their expected location in the input XML document.

That said, if we focus on your stated desired solution:

"The point is that there is separate grouping for each <Item> into it's own <table> and inside that <table> there is groupping by <ItemTextsType>"

...then this ought to get you in the right direction.

When this XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key
    name="kItemTextByType"
    match="ItemText"
    use="concat(generate-id(ancestor::Item[1]), '+', ItemTextsType)" />

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <table width="100%" border="1" style="display: block;">
      <tbody>
        <tr>
          <td id="SelectedRowLinkageContents">
            <xsl:apply-templates />
          </td>
        </tr>
      </tbody>
    </table>
  </xsl:template>

  <xsl:template match="Item">
    <table width="100%" dir="ltr">
      <tbody>
        <tr style="background-color: #507CD1; text-align: center">
          <td colspan="3" style="font: bold; color: white">
            <xsl:value-of select="concat('Item', position())" />
          </td>
        </tr>
        <xsl:apply-templates 
          select="ItemTexts/ItemText[
            generate-id() = 
            generate-id(
              key(
                'kItemTextByType', 
                 concat(generate-id(current()), '+', ItemTextsType)
              )[1]
            )
          ]">
          <xsl:sort select="ItemTextsType" />
        </xsl:apply-templates>
      </tbody>
    </table>
  </xsl:template>

  <xsl:template match="ItemText">
    <tr>
      <td style="height: 35px; font: bold; color: #507CD1;">
        <xsl:value-of select="ItemTextsType" />
      </td>
    </tr>
    <xsl:for-each
      select="key(
        'kItemTextByType', 
        concat(
          generate-id(ancestor::Item[1]),
          '+',
          ItemTextsType
        )
      )"
    >
      <xsl:sort select="ItemTextsTypeDesc" />
      <tr>
        <td>
          <xsl:value-of select="ItemTextsTypeDesc" />
        </td>
      </tr>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

...is applied to the provided input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Items>
  <Item>
    <ItemTexts>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
        <ItemTextsLine>1</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
        <ItemTextsLine>2</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
        <ItemTextsLine>3</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
        <ItemTextsLine>4</ItemTextsLine>
      </ItemText>
    </ItemTexts>
  </Item>
  <Item>
    <ItemTexts>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
        <ItemTextsLine>1</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
        <ItemTextsLine>2</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
        <ItemTextsLine>3</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
        <ItemTextsLine>4</ItemTextsLine>
      </ItemText>
    </ItemTexts>
  </Item>
  <Item>
    <ItemTexts>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
        <ItemTextsLine>1</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type1</ItemTextsType>
        <ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
        <ItemTextsLine>2</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
        <ItemTextsLine>3</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
        <ItemTextsLine>4</ItemTextsLine>
      </ItemText>
    </ItemTexts>
  </Item>
  <Item>
    <ItemTexts>
      <ItemText>
        <ItemTextsType>type3</ItemTextsType>
        <ItemTextsTypeDesc>description31</ItemTextsTypeDesc>
        <ItemTextsLine>1</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type3</ItemTextsType>
        <ItemTextsTypeDesc>description32</ItemTextsTypeDesc>
        <ItemTextsLine>2</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
        <ItemTextsLine>3</ItemTextsLine>
      </ItemText>
      <ItemText>
        <ItemTextsType>type2</ItemTextsType>
        <ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
        <ItemTextsLine>4</ItemTextsLine>
      </ItemText>
    </ItemTexts>
  </Item>
</Items>

...the wanted result is (I think) produced:

<table width="100%" border="1" style="display: block;">
  <tbody>
    <tr>
      <td id="SelectedRowLinkageContents">
        <table width="100%" dir="ltr">
          <tbody>
            <tr style="background-color: #507CD1; text-align: center">
              <td colspan="3" style="font: bold; color: white">Item1</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type1</td>
            </tr>
            <tr>
              <td>description11</td>
            </tr>
            <tr>
              <td>description12</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type2</td>
            </tr>
            <tr>
              <td>description21</td>
            </tr>
            <tr>
              <td>description22</td>
            </tr>
          </tbody>
        </table>
        <table width="100%" dir="ltr">
          <tbody>
            <tr style="background-color: #507CD1; text-align: center">
              <td colspan="3" style="font: bold; color: white">Item2</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type1</td>
            </tr>
            <tr>
              <td>description11</td>
            </tr>
            <tr>
              <td>description12</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type2</td>
            </tr>
            <tr>
              <td>description21</td>
            </tr>
            <tr>
              <td>description22</td>
            </tr>
          </tbody>
        </table>
        <table width="100%" dir="ltr">
          <tbody>
            <tr style="background-color: #507CD1; text-align: center">
              <td colspan="3" style="font: bold; color: white">Item3</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type1</td>
            </tr>
            <tr>
              <td>description11</td>
            </tr>
            <tr>
              <td>description12</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type2</td>
            </tr>
            <tr>
              <td>description21</td>
            </tr>
            <tr>
              <td>description22</td>
            </tr>
          </tbody>
        </table>
        <table width="100%" dir="ltr">
          <tbody>
            <tr style="background-color: #507CD1; text-align: center">
              <td colspan="3" style="font: bold; color: white">Item4</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">type2</td>
            </tr>
            <tr>
              <td>description21</td>
            </tr>
            <tr>
              <td>description22</td>
            </tr>
            <tr>
              <td style="height: 35px; font: bold; color: #507CD1;">
              type3</td>
            </tr>
            <tr>
              <td>description31</td>
            </tr>
            <tr>
              <td>description32</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

...which, when rendered in an HTML page, looks like this:

HTML table

ABach
  • 3,743
  • 5
  • 25
  • 33
  • You are absolutely right in your comments, of course I need a table for each Item and the description should be consistent. I was a bit lazy to complete the hole example and to check the consistency of all descriptions. – Polina F. Nov 14 '12 at 08:32
  • @PolinaFeterman - does this answer accomplish what you were looking for? – ABach Nov 14 '12 at 08:32
  • I try it just now because on top of it I had to simplify the xml because the original xml I have is more complex and also the required html is more complex – Polina F. Nov 14 '12 at 08:56
  • Hi , wood it be too cheek to ask if you could re write the answer using `` because in my real code I need many more information from each `` and then all the info gets arranged into HUGE table with row `` for each `` and MANY cells `` in which the result table of EACH `` is only in one of the cells `` . Each table of each `` is for separate `` in this HUGE table. – Polina F. Nov 14 '12 at 09:16
  • I have edited the question once again with a better explanation on the needed outcome html table. – Polina F. Nov 14 '12 at 09:37
  • @PolinaFeterman - I answered the original question; continuous editing pollutes the question/answer such that it won't be useful to future readers. Please post your new question as a separate SO question. – ABach Nov 14 '12 at 09:47
  • Done - title of a question : xsl grouping by xml element for repetitive nodes in xslt1 into html table output – Polina F. Nov 14 '12 at 10:46