如何将同级别的xml元素组织到不同的层次结构中

时间:2015-10-31 05:16:51

标签: xml xslt

我有这个元素

<products>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>C</gih>
</item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>A</gih>
</item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>A</gih>
</item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>C</gih>
</item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>A</gih>
</item>
</products>

这必须转换为

<products>
<message>
 <item>
  <abc>2</abc>
  <def>m</def>
  <gih>C</gih>
 </item>
 <item>
  <abc>2</abc>
  <def>m</def>
  <gih>A</gih>
 </item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>A</gih>
 </item>
</message>
<message>
 <item>
  <abc>2</abc>
  <def>m</def>
  <gih>C</gih>
</item>
<item>
 <abc>2</abc>
 <def>m</def>
 <gih>A</gih>
</item>
</message>
</products>

实际上,只要元素gih具有值C,就必须生成新消息。 xml始终以C开头,然后是As。

in gih元素表示必须附加该项目。

有人可以建议使用xslt吗?非常感谢!

1 个答案:

答案 0 :(得分:1)

在XSLT 2.0中这很容易做到 - 在XSLT 1.0中不那么简单:

XSLT 2.0

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

<xsl:template match="/products">
    <xsl:copy>
        <xsl:for-each-group select="item" group-starting-with="item[gih='C']">
            <message>
                <xsl:copy-of select="current-group()" />
            </message>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

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:key name="item-by-leader" match="item[not(gih='C')]" use="generate-id(preceding-sibling::item[gih='C'][1])" />

<xsl:template match="/products">
    <xsl:copy>
        <xsl:for-each select="item[gih='C']">
            <message>
                <xsl:copy-of select=". | key('item-by-leader', generate-id())" />
            </message>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>