Xslt 分组XML元素
我正在尝试对以下XML进行分组:Xslt 分组XML元素,xslt,xslt-2.0,Xslt,Xslt 2.0,我正在尝试对以下XML进行分组: <?xml version="1.0" encoding="UTF-8"?> <EDIFACT segmentDelimiter="'" itemDelimiter="+" elementDelimiter=":" decimalCharacter="." escapeCharacter="?"> <Envelope count='1'> <UNB>
<?xml version="1.0" encoding="UTF-8"?>
<EDIFACT segmentDelimiter="'" itemDelimiter="+" elementDelimiter=":" decimalCharacter="." escapeCharacter="?">
<Envelope count='1'>
<UNB>
<I1>
<E1>UNOA</E1>
<E2>2</E2>
</I1>
</UNB>
<Message count='1'>
<UNH>
<I1>
<E1>8351519</E1>
</I1>
<I2>
<E1>MESTYP</E1>
<E2>D</E2>
<E3>96A</E3>
<E4>UN</E4>
</I2>
</UNH>
<BGM>
<I1>
<E1>351</E1>
</I1>
<I2>
<E1>8351519</E1>
</I2>
</BGM>
<DTM>
<I1>
<E1>137</E1>
<E2>20130429</E2>
<E3>102</E3>
</I1>
</DTM>
<DTM>
<I1>
<E1>132</E1>
<E2>20130521</E2>
<E3>102</E3>
</I1>
</DTM>
<CPS>
<I1>
<E1>1</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015000</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>305</E2>
</I1>
</QTY>
<SGP>
<I1>
<E1>KA02</E1>
<E2>129</E2>
</I1>
</SGP>
<SGP>
<I1>
<E1>0001</E1>
<E2>156</E2>
</I1>
</SGP>
<SGP>
<I1>
<E1>1ST CHOICE</E1>
<E2>189</E2>
</I1>
</SGP>
<CPS>
<I1>
<E1>2</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015010</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>424</E2>
</I1>
</QTY>
<SGP>
<I1>
<E1>KA02</E1>
<E2>129</E2>
</I1>
</SGP>
<SGP>
<I1>
<E1>0001</E1>
<E2>156</E2>
</I1>
</SGP>
<SGP>
<I1>
<E1>1ST CHOICE</E1>
<E2>189</E2>
</I1>
</SGP>
<UNT>
<I1>
<E1>89</E1>
</I1>
<I2>
<E1>8351519</E1>
</I2>
</UNT>
</Message>
<UNZ>
<I1>
<E1>1</E1>
</I1>
<I2>
<E1>8351519</E1>
</I2>
</UNZ>
</Envelope>
</EDIFACT>
这几乎是正确的。我只遗漏了结果中的第一个
CPS
元素。当使用以开头的组时,为了避免包装不属于组的元素,我建议使用
<xsl:template match="Message">
<!-- Copy 'Message' node itself -->
<xsl:copy>
<!-- Also copy attributes of 'Message' node -->
<xsl:apply-templates select="@*" />
<!-- Group by CPS nodes -->
<xsl:for-each-group select="*" group-starting-with="CPS">
<!-- Before any CPS node, put a articleLine node (UNH gets included also at this moment and UNT) -->
<xsl:choose>
<xsl:when test="self::CPS">
<articleLine>
<xsl:apply-templates select="current-group()" />
</articleLine>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Identity template (copies all nodes and attributes) -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- When 'Message' node is found, do following -->
<xsl:template match="Message">
<!-- Copy 'Message' node itself -->
<xsl:copy>
<!-- Also copy attributes of 'Message' node -->
<xsl:apply-templates select="@*" />
<!-- Group by CPS nodes -->
<xsl:for-each-group select="*" group-starting-with="CPS">
<!-- Before any CPS node, put a articleLine node (UNH gets included also at this moment and UNT) -->
<articleLine>
<xsl:apply-templates select="current-group()" />
</articleLine>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<!-- When 'Message' node is found, do following -->
<xsl:template match="Message">
<!-- Copy 'Message' node itself -->
<xsl:copy>
<!-- Also copy attributes of 'Message' node -->
<xsl:apply-templates select="@*" />
<!--xsl:copy-of select="UNH|BGM|DTM" / -->
<xsl:copy-of select="CPS[1]/preceding-sibling::*" />
<!-- Group by CPS nodes -->
<xsl:for-each-group select="CPS[1]/following-sibling::*[name()!='UNT']" group-starting-with="CPS">
<!-- Before any CPS node, put a articleLine node (UNH gets included also at this moment) -->
<articleLine>
<xsl:apply-templates select="current-group()" />
</articleLine>
</xsl:for-each-group>
<xsl:copy-of select="UNT" />
</xsl:copy>
</xsl:template>
<xsl:template match="Message">
<!-- Copy 'Message' node itself -->
<xsl:copy>
<!-- Also copy attributes of 'Message' node -->
<xsl:apply-templates select="@*" />
<!-- Group by CPS nodes -->
<xsl:for-each-group select="*" group-starting-with="CPS">
<!-- Before any CPS node, put a articleLine node (UNH gets included also at this moment and UNT) -->
<xsl:choose>
<xsl:when test="self::CPS">
<articleLine>
<xsl:apply-templates select="current-group()" />
</articleLine>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Identity template (copies all nodes and attributes) -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- When 'Message' node is found, do following -->
<xsl:template match="Message">
<!-- Copy 'Message' node itself -->
<xsl:copy>
<!-- Also copy attributes of 'Message' node -->
<xsl:apply-templates select="@*" />
<!-- Group by CPS nodes -->
<xsl:for-each-group select="* except UNT" group-starting-with="CPS">
<!-- Before any CPS node, put a articleLine node (UNH gets included also at this moment and UNT) -->
<xsl:choose>
<xsl:when test="self::CPS">
<articleLine>
<xsl:apply-templates select="current-group()" />
</articleLine>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
<xsl:apply-templates select="UNT"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>