0

I have a following XML file (that I do not control):

<recordset>
    <row>
      <field name="orderid">1</field>
      <field name="orderlineid">1</field>
      <field name="quantity">2</field>
      <field name="item">Thing 1</field>
    </row>
    <row>
      <field name="orderid">2</field>
      <field name="orderlineid">2</field>
      <field name="quantity">1</field>
      <field name="item">Thing 3</field>
    </row>
    <row>
      <field name="orderid">2</field>
      <field name="orderlineid">3</field>
      <field name="quantity">1</field>
      <field name="item">Thing 2</field>
    </row>
    <row>
      <field name="orderid">3</field>
      <field name="orderlineid">4</field>
      <field name="quantity">3</field>
      <field name="item">Other</field>
    </row>
</recordset>

And I am struggling with XSLT and for-each-group to group by order id and to generate a following XML:

<orders>   
   <order id="1" lines = "1">
        <orderline id = "1" quantity = "2" item = "Thing"> </orderline>
    </order>
    <order id="2" lines = "2">
        <orderline id = "2"  quantity = "1" item = "Thing 3"> </orderline>
        <orderline id = "3"  quantity = "1" item = "Thing 2"> </orderline>
    </order>
    <order id="3" lines="1">
        <orderline id = "4" quantity = "3" item = "Other"> </orderline>
    </order>
</orders>

Here is my attend so far:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:key name="keyOrder" match="row" use="field/@name = 'COMMANDE'" />
    <xsl:template match="resultset">
        <commandes xmlns:od="http://www.w3.org/2001/XMLSchema-instance">
            <xsl:apply-templates/>
        </commandes>
    </xsl:template>
    <xsl:template match="row">
        <orders>    
            <xsl:for-each-group select="./child::*" group-by="field/@name = 'orderid'">
                <order>
                    <xsl:value-of select="field[@name = 'COMMANDE']"/>
                </order>
            </xsl:for-each-group>
        </orders>
    </xsl:template> 
</xsl:stylesheet>

How can I :

  • Group based on a child node
  • Count how many lines I have in each group?
4
  • Attempt added. I can only use XSLT 1.0 processor (not sure if it has an impact) Commented Jul 2, 2019 at 16:07
  • Is there an alternative using XSLT 1.0? Commented Jul 2, 2019 at 16:09
  • I've added more complete extracts/full xsl Commented Jul 2, 2019 at 16:15
  • XSLT does not match input. recordset != resultset and where is @name='COMMANDE']? Also, you removed desired output. Commented Jul 2, 2019 at 16:27

1 Answer 1

1

Consider the Muenchian Grouping which you begin with defining <xsl:key>:

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

    <xsl:key name="keyOrder" match="row" use="field[@name='orderid']"/>

    <xsl:template match="recordset">
        <commandes xmlns:od="http://www.w3.org/2001/XMLSchema-instance">
            <xsl:apply-templates select="row[generate-id() =
                        generate-id(key('keyOrder', field[@name='orderid'])[1])]"/>
        </commandes>
    </xsl:template>

    <xsl:template match="row">
        <order id = "{field[@name='orderid']}" 
               lines = "{count(. | key('keyOrder', field[@name='orderid']))}"> 

                <xsl:for-each select="key('keyOrder', field[@name='orderid'])">
                    <orderline id = "{field[@name='orderlineid']}" 
                               quantity = "{field[@name='quantity']}"
                               item = "{field[@name='item']}" />
                </xsl:for-each>

        </order>
    </xsl:template> 

</xsl:stylesheet>

XSLT Fiddle Demo

Output

<?xml version="1.0" encoding="UTF-8"?>
<commandes xmlns:od="http://www.w3.org/2001/XMLSchema-instance">
   <order id="1" lines="1">
      <orderline id="1" quantity="2" item="Thing 1"/>
   </order>
   <order id="2" lines="2">
      <orderline id="2" quantity="1" item="Thing 3"/>
      <orderline id="3" quantity="1" item="Thing 2"/>
   </order>
   <order id="3" lines="1">
      <orderline id="4" quantity="3" item="Other"/>
   </order>
</commandes>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for your patience and your time. Muenchian is working fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.