我正在尝试对以下 XML 进行分组:
<?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>
我尝试获得以下输出:
<?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>
<articleLine>
<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>
</articleLine>
<articleLine>
<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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>3</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015100</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>139</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>4</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015130</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>100</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>5</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015180</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>55</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>6</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015200</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>50</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>7</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700515230</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>13</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>8</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015240</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>5</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>9</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015260</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>105</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>10</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015300</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>75</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>11</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700015360</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>28</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>12</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700515370</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>10</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>
</articleLine>
<articleLine>
<CPS>
<I1>
<E1>13</E1>
</I1>
</CPS>
<LIN>
<I1>
<E1/>
</I1>
<I2>
<E1/>
</I2>
<I3>
<E1>859700016030</E1>
</I3>
</LIN>
<QTY>
<I1>
<E1>12</E1>
<E2>35</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>
</articleLine>
<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>
我目前使用的 XSLT:
<?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>
我面临的问题是我的结果中的第一组是第一个 CPS 元素之前的所有内容。我不想将此添加到名为“articleLine”的组中。同样在最后一组添加了 UNT,它应该是“articleLine”的一部分。
我可以使用xsl:for-each-group
吗?还是我应该自定义分组?
** 编辑 ** 当我使用以下模板时:
<!-- 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>
这几乎是正确的。我只错过了CPS
结果中的第一个元素。