使用XSLT转换XML时的分组问题(不支持for-each-group)
解决XSLT分组转换问题(不支持for-each-group场景)
在使用XSLT将XML转换为XML时,遇到分组信息丢失的问题:无法保留输入XML中的组名称及多组结构,只能生成固定名称的组。注意:系统不支持for-each-group和current-group()函数,使用会触发解析错误。同时需要将所有transaction组统一放入transactions父节点中。
示例输入XML
<?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代码片段
<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>
当前错误输出
<?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>
期望输出XML
<?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>
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <Statement> <!-- 处理field节点 --> <xsl:for-each select="Statement/field"> <xsl:element name="{normalize-space(@name)}"> <xsl:value-of select="normalize-space(.)"/> </xsl:element> </xsl:for-each> <grouping> <!-- 处理非transaction的组 --> <xsl:for-each select="Statement/group[@name != 'transaction']"> <xsl:element name="{normalize-space(@name)}"> <xsl:for-each select="member"> <xsl:element name="{normalize-space(@name)}"> <xsl:value-of select="normalize-space(.)"/> </xsl:element> </xsl:for-each> </xsl:element> </xsl:for-each> <!-- 处理transaction组,包裹到transactions节点中 --> <xsl:if test="Statement/group[@name = 'transaction']"> <transactions> <xsl:for-each select="Statement/group[@name = 'transaction']"> <transaction> <xsl:for-each select="member"> <xsl:element name="{normalize-space(@name)}"> <xsl:value-of select="normalize-space(.)"/> </xsl:element> </xsl:for-each> </transaction> </xsl:for-each> </transactions> </xsl:if> </grouping> </Statement> </xsl:template> </xsl:stylesheet>
逻辑说明
- 字段处理:保留原有
field节点的转换逻辑,同时用normalize-space()去除内容和属性值的多余空格 - 普通组处理:遍历所有非
transaction的group节点,直接以组的@name作为元素名,内部遍历member生成子节点 - transaction组处理:先判断是否存在
transaction组,若存在则生成transactions父节点,再遍历所有transaction组,每个组生成transaction子节点,内部处理member生成对应字段 - 全程未使用
for-each-group或current-group()函数,适配系统限制
内容的提问来源于stack exchange,提问作者Nicky
相关产品推荐
相关产品推荐

