0

I am having problem with grouping while transforming xml to xml using xslt. I found out where the problem comes from but still don't know how to fix it.

I am unable to fetch the group name/multiple groups in the output after XSLT transformation. I'm only able to fetch the group name provided in the XSLT code but not the group name present in "input xml". Please be noted that our system doesn't support for-each-group and current-group() functions, resulting in XML parse error.

This is the sample input

<?xml version="1.0" encoding="UTF-8"?>
<Statement xmlns:xsi="http://www.w.org/2001/XMLSchemainstance">
<field name="statementNumber"> 25 </field>
<field name="Online"> Yes </field>
<field name="iban"> xxxx </field>
<group name="addressFields">
<member name="addressLine1"> flat 2 ted apartments </member>
<member name="addressLine2"> samurai street </member>
<member name="town"> Jaisalmer </member>
<member name="postCode"> 678222 </member>
<member name="country"> Indonesia </member>
</group>
<group name="transaction">
<member name="type"> cash </member>
<member name="amount"> 5228 </member>
<member name="txnDate"> 28 oct 2022 </member>
<member name="reference"> ATM withdrawal </member>
</group>
<group name="transaction">
<member name="type"> card </member>
<member name="amount"> 3378 </member>
<member name="txnDate"> 28 nov 2022 </member>
<member name="reference"> Super market purchase </member>
</group>
</Statement>

XSLT code snippet:

<xsl:output method="xml" indent="yes">
<xsl:template match="/">
<Statement>
  <xsl:for-each select="Statement/field">
    <xsl:element name="{@name}">
    <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
  <xsl:element name="grouping">
    <xsl:for-each select="Statement/group/member">
      <xsl:element name="{@name}">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>     
   </xsl:element>
</Statement>

Actual output (incorrect - need group names):

<?xml version="1.0" encoding="UTF-8"?>
<Statement>
<statementNumber>25</statementNumber>
<Online>Yes</Online>
<iban>xxxx</iban>
<grouping>
<addressLine1>flat 2 ted apartments</addressLine1>
<addressLine2>samurai street</addressLine2>
<town>Jaisalmer</town>
<postCode>678222</postCode>
<country>Indonesia</country>
<type>cash</type>
<amount>5228</amount>
<txnDate>28 oct 2022</txnDate>
<reference>ATM withdrawal</reference>
<type>card</type>
<amount>3378</amount>
<txnDate>28 nov 2022</txnDate>
<reference>Super market purchase</reference>
</grouping>
</Statement>

If you see above, the group names are completely missing; not appearing in the output. I tried many ways to achieve it, but either group name is missing or all the group fields are missing. I'm unable to fetch both of them. Moreover, I have a requirement of adding all <transaction> group blocks within another super group block <transactions>

Expected output

<?xml version="1.0" encoding="UTF-8"?>
<Statement>
<statementNumber>25</statementNumber>
<Online>Yes</Online>
<iban>xxxx</iban>
<grouping>
<addressFields>
<addressLine1>flat 2 ted apartments</addressLine1>
<addressLine2>samurai street</addressLine2>
<town>Jaisalmer</town>
<postCode>678222</postCode>
<country>Indonesia</country>
</addressFields>
<transactions>
<transaction>
<type>cash</type>
<amount>5228</amount>
<txnDate>28 oct 2022</txnDate>
<reference>ATM withdrawal</reference>
</transaction>
<transaction>
<type>card</type>
<amount>3378</amount>
<txnDate>28 nov 2022</txnDate>
<reference>Super market purchase</reference>
</transaction>
</transactions>
</grouping>
</Statement>
Nicky
  • 15
  • 4
  • 2
    Please edit your question and provide a well-formed XML as the input example: `` does not match ``. Also, if your system doesn't support `for-each-group` then you should not tag your question as `xslt-2.0`. – michael.hor257k Jan 24 '23 at 20:22
  • Apologies... Thanks for your comments, corrected now! – Nicky Jan 25 '23 at 01:03

1 Answers1

0

I am guessing (!) you want to do something like:

XSLT 1.0

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

<xsl:template match="/Statement">
    <xsl:copy>
        <xsl:apply-templates select="field"/>
        <grouping>
            <xsl:apply-templates select="group[@name!='transaction']"/>
            <transactions>
                <xsl:apply-templates select="group[@name='transaction']"/>
            </transactions>
        </grouping>
    </xsl:copy>
</xsl:template>

<xsl:template match="group | field | member">
    <xsl:element name="{@name}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Given a well-formed (!) XML as the input:

XML

<Statement xmlns:xsi="http://www.w.org/2001/XMLSchemainstance">
<field name="statementNumber"> 25 </field>
<field name="Online"> Yes </field>
<field name="iban"> xxxx </field>
<group name="addressFields">
<member name="addressLine1"> flat 2 ted apartments </member>
<member name="addressLine2"> samurai street </member>
<member name="town"> Jaisalmer </member>
<member name="postCode"> 678222 </member>
<member name="country"> Indonesia </member>
</group>
<group name="transaction">
<member name="type"> cash </member>
<member name="amount"> 5228 </member>
<member name="txnDate"> 28 oct 2022 </member>
<member name="reference"> ATM withdrawal </member>
</group>
<group name="transaction">
<member name="type"> card </member>
<member name="amount"> 3378 </member>
<member name="txnDate"> 28 nov 2022 </member>
<member name="reference"> Super market purchase </member>
</group>
</Statement>

this will return:

Result

<?xml version="1.0" encoding="UTF-8"?>
<Statement xmlns:xsi="http://www.w.org/2001/XMLSchemainstance">
   <statementNumber> 25 </statementNumber>
   <Online> Yes </Online>
   <iban> xxxx </iban>
   <grouping>
      <addressFields>
         <addressLine1> flat 2 ted apartments </addressLine1>
         <addressLine2> samurai street </addressLine2>
         <town> Jaisalmer </town>
         <postCode> 678222 </postCode>
         <country> Indonesia </country>
      </addressFields>
      <transactions>
         <transaction>
            <type> cash </type>
            <amount> 5228 </amount>
            <txnDate> 28 oct 2022 </txnDate>
            <reference> ATM withdrawal </reference>
         </transaction>
         <transaction>
            <type> card </type>
            <amount> 3378 </amount>
            <txnDate> 28 nov 2022 </txnDate>
            <reference> Super market purchase </reference>
         </transaction>
      </transactions>
   </grouping>
</Statement>

Note that this has nothing to do with grouping; your input is already grouped.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thank you very much for the quick response, I will apply the suggested solution and get back to you.. :) – Nicky Jan 25 '23 at 01:04
  • Hello Michael, I have just tried your solution. It worked perfectly. Just one thing to consider - in the output result, there’s a space coming up before and after the value. I mean card instead of card.. can you kindly suggest how I can remove these spaces? Please see, I was not getting these spaces with the earlier code I tried but had issues with group names, which is resolved after I applied your solution. Thank you! – Nicky Jan 25 '23 at 11:01
  • *""I was not getting these spaces with the earlier code"* Yes you were. These spaces exist in the input and are preserved in the output. If you want to remove them, then add another template: ` `. – michael.hor257k Jan 25 '23 at 11:09
  • Thanks Michael, i have added the above template as suggested.. it worked!! Just one last thing - is it possible to change the tag in output result “” to omitting the ‘namespace’ and getting either the tag name in camelCase (with ‘s’ in lower case in this example) or by replacing it with completely a new tag label like ‘document’ (). Please see that the input still contains stays the same as it is. Thank you! – Nicky Jan 25 '23 at 14:17
  • And what if I want to have another super group like in the output xml. For example if I have two addresses in the input, i would like to keep them under …….….. . I tried adding another template as but it resulted only one super group coming up, not both. Kindly check and advise on this as well along with the above one. Thank you! – Nicky Jan 25 '23 at 15:38
  • I suggest you post new question/s focusing on your new requirement/s. – michael.hor257k Jan 25 '23 at 16:12
  • Hi Michael, I have posted a new question as suggested. Thank you https://stackoverflow.com/questions/75241444/problem-with-multiple-groups-while-transforming-xml-using-xslt – Nicky Jan 26 '23 at 01:06