分组XML元素

时间:2013-10-14 11:07:51

标签: xslt xslt-2.0

我正在尝试将以下XML分组:

<?xml version="1.0" encoding="UTF-8"?>
<EDIFACT segmentDelimiter="&#39;" 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元素。

1 个答案:

答案 0 :(得分:1)

使用group-starting-with时,为了避免包装不属于某个组的元素,我建议使用

<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>

如果您不想对UNT元素进行分组,请使用

<?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>