按子节点嵌套父节点



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

相关内容

  • 没有找到相关文章

最新更新