在XML中有0-n个属性的项,每个属性都应该复制一个项作为新项,但只有一个属性。
给定的XML如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<items>
<item>
<name>A</name>
<attributes>
<attribute>
<key>attribute1</key>
<value>1</value>
</attribute>
</attributes>
</item>
<item>
<name>B</name>
</item>
<item>
<name>C</name>
<attributes>
<attribute>
<key>attribute1</key>
<value>5</value>
</attribute>
<attribute>
<key>attribute2</key>
<value>2</value>
</attribute>
<attribute>
<key>attribute3</key>
<value>1</value>
</attribute>
</attributes>
</item>
</items>
结果应该是:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<item>
<name>A</name>
<attribute_key>attribute1</attribute_key>
<attribute_value>1</attribute_value>
</item>
<item>
<name>B</name>
</item>
<item>
<name>C</name>
<attribute_key>attribute1</attribute_key>
<attribute_value>5</attribute_value>
</item>
<item>
<name>C</name>
<attribute_key>attribute2</attribute_key>
<attribute_value>2</attribute_value>
</item>
<item>
<name>C</name>
<attribute_key>attribute3</attribute_key>
<attribute_value>1</attribute_value>
</item>
</root>
我有什么?
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:if test="not(attributes/attribute)">
<item>
<xsl:apply-templates select="@* | node()"/>
</item>
</xsl:if>
<xsl:for-each select="./attributes/attribute">
<xsl:copy-of select="ancestor::item"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
所以,父"item"节点得到正确复制,但我如何从for-each中删除除属性外的所有属性,并将该属性作为"item"的直接子属性?
与其复制整个item
节点,不如手动创建一个新的item
,并只复制它的子节点(除了attributes
)
<xsl:for-each select="attributes/attribute">
<item>
<xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>
<!-- Process attributes here -->
</item>
</xsl:for-each>
处理属性只是处理子属性的问题,并使用xsl:element
创建新属性
<xsl:for-each select="*">
<xsl:element name="attribute_{local-name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:if test="not(attributes/attribute)">
<item>
<xsl:apply-templates select="@* | node()"/>
</item>
</xsl:if>
<xsl:for-each select="attributes/attribute">
<item>
<xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>
<xsl:for-each select="*">
<xsl:element name="attribute_{local-name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</item>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
或者如果你想采用更基于模板的方法,这也应该工作
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[attributes/attribute]">
<xsl:apply-templates select="attributes/attribute" />
</xsl:template>
<xsl:template match="item">
<item>
<xsl:apply-templates select="@* | node()"/>
</item>
</xsl:template>
<xsl:template match="attribute">
<item>
<xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>
<xsl:apply-templates select="*" />
</item>
</xsl:template>
<xsl:template match="attribute/*">
<xsl:element name="attribute_{local-name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
看一下下面的脚本,它将解释你想要的是你正在寻找:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:template match="/">
<root>
<xsl:apply-templates select="items/item" />
</root>
</xsl:template>
<xsl:template match="item">
<xsl:if test="not(attributes/attribute)">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:if>
<xsl:apply-templates select="attributes/attribute">
<!-- sending value of name tag to a template matching attribute tag -->
<xsl:with-param name="name" select="name"></xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<!--Another template for attribute tag that will help individually tracking of attribute -->
<xsl:template match="attribute">
<!-- Taking value of name tag -->
<xsl:param name="name"></xsl:param>
<item>
<name>
<xsl:value-of select="$name" />
</name>
<attribute_key>
<xsl:value-of select="key" />
</attribute_key>
<attribute_value>
<xsl:value-of select="value" />
</attribute_value>
</item>
</xsl:template>