子节点

时间:2015-08-03 07:03:41

标签: xslt xslt-1.0

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

所以,父母&#34;项目&#34;节点被正确复制但如何删除所有属性,但是从for-each中删除该属性并将该属性作为&#34; item&#34;的直接子节点??

2 个答案:

答案 0 :(得分:1)

不是复制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>

答案 1 :(得分:0)

看一下下面的脚本,它会解释你想要的是:

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