Djuric
Djuric

Reputation: 45

XSLT 1.0 grouping based on start of each line in XML

I guess this question is fairly simple for XSLT-gurus here on SO.

I have the below input XML:

<?xml version="1.0" encoding="utf-8"?>
<rows xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <row>72906505066990543065    ABCDEF</row>
    <row>72916505066990608306    ABCDEF</row>
    <row>72916505066990665660    EFGHIJ</row>
    <row>72916505066990665660    EFGHIJ</row>
    <row>72916505066990684364    KLMNOP</row>
    <row>72916505066990684364    KLMNOP</row>
    <row>72916505066990684364    KLMNOP</row>
    <row>72916505066990722859    QRSTUV</row>
    <row>72916505066990722859    QRSTUV</row>
</rows>

I want to be able to group the row elements so that I can iterate them using a for-each loop. The grouping should be based on the first 20 numbers on each row.

Can someone out there help me out howto accomplish this?

The output XML should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<RowsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RowList>
  <Row>
     <LineID>
        <Identity>72906505066990543065</Identity>
     </LineID>
     <RowData>
           <Data>ABCDEF<Data/>
     </RowData>
  </Row>
  <Row>
     <LineID>
        <Identity>72916505066990608306</Identity>
     </LineID>
     <RowData>
           <Data>ABCDEF<Data/>
     </RowData>
  </Row>
  <Row>
     <LineID>
        <Identity>72916505066990665660</Identity>
     </LineID>
     <RowData>
           <Data>EFGHIJ<Data/>
     </RowData>
     <RowData>
           <Data>EFGHIJ<Data/>
     </RowData>
  </Row>
</RowList>
</RowsFile> And so on....

Upvotes: 0

Views: 76

Answers (1)

Djuric
Djuric

Reputation: 45

Thank you very much Michael! You pointed me in the right direction.

In the end I solved my problem like this:

Input XML:

<?xml version="1.0" encoding="utf-8"?>
<rows xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>72906505066990543065    ABCDEF</row>
<row>72916505066990608306    ABCDEF</row>
<row>72916505066990665660    EFGHIJ</row>
<row>72916505066990665660    EFGHIJ</row>
<row>72916505066990684364    KLMNOP</row>
<row>72916505066990684364    KLMNOP</row>
<row>72916505066990684364    KLMNOP</row>
<row>72916505066990722859    QRSTUV</row>
<row>72916505066990722859    QRSTUV</row>
</rows>

XSLT:

<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:transform version = "1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="Collection" match="row" use="substring(., 1, 20)" />                 

    <xsl:template match="rows">
        <RowsFile>
            <RowList>
            <!-- Loop all unique groups -->
            <xsl:for-each select="row[count(. | key('Collection', substring(., 1, 20))[1]) = 1]">
                <Grouped>
                    <Data>
                            <xsl:value-of select="normalize-space(substring(.,1,20))"/>
                    </Data>

                <!-- Loop all values in group-->
                <xsl:for-each select="key('Collection', substring(., 1, 20))">
                    <Value>
                        <Data><xsl:value-of select="normalize-space(substring(.,25,6))"/></Data>
                    </Value>
                </xsl:for-each>

                </Grouped>  

            </xsl:for-each>
            </RowList>
        </RowsFile>
    </xsl:template>

</xsl:transform>

Output:

<?xml version="1.0" encoding="UTF-8"?>
<RowsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RowList>
    <Grouped>
      <Data>72906505066990543065</Data>
      <Value>
        <Data>ABCDEF</Data>
      </Value>
    </Grouped>
    <Grouped>
      <Data>72916505066990608306</Data>
      <Value>
        <Data>ABCDEF</Data>
      </Value>
    </Grouped>
    <Grouped>
      <Data>72916505066990665660</Data>
      <Value>
        <Data>EFGHIJ</Data>
      </Value>
      <Value>
        <Data>EFGHIJ</Data>
      </Value>
    </Grouped>
    <Grouped>
      <Data>72916505066990684364</Data>
      <Value>
        <Data>KLMNOP</Data>
      </Value>
      <Value>
        <Data>KLMNOP</Data>
      </Value>
      <Value>
        <Data>KLMNOP</Data>
      </Value>
    </Grouped>
    <Grouped>
      <Data>72916505066990722859</Data>
      <Value>
        <Data>QRSTUV</Data>
      </Value>
      <Value>
        <Data>QRSTUV</Data>
      </Value>
    </Grouped>
  </RowList>
</RowsFile>

Upvotes: 2

Related Questions