xsl只能递归复制一些元素并删除一些后代

时间:2011-09-02 11:28:11

标签: xml xslt xpath

我想改造

<?xml version="1.0" ?>
<mydoc>
    <file>
        <colors>
            <blue />
            <red />
            <green />
        </colors>
        <secret>
            <username />
            <password />
        </secret>
    </file>
</mydoc>

<?xml version="1.0" ?>
<colors>
  <blue />
  <red />
</colors>

简单来说,我想递归复制colors元素,包括文本,忽略XML文档的其余部分并丢弃green元素。

有一些解决方案可以使用上面的示例,但如果XML略有不同,则会失败。例如,在颜色元素下添加嵌套元素,或在颜色<层次结构中添加其他元素/ strong>元素,或颜色元素范围内的文本(GOOD TEXT)和另一个超出其范围的文本(BAD TEXT)。

<?xml version="1.0" ?>
<mydoc>
    <file>
        <colors>
            <nest>
              <blue />
              <red />
              <green />
            </nest>
            GOOD TEXT
        </colors>
        <secret>
            <username />
            <password />
        </secret>
        BAD TEXT
    </file>
    <other>BAD TEXT TWO</other>
</mydoc>

我最感兴趣的是一个通用的解决方案,而不是根据此处提供的例子进行自定义。

2 个答案:

答案 0 :(得分:2)

这种新变换足以复制颜色元素,无论其父级是什么

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/mydoc/file/colors">
        <xsl:variable name="colors_parent"
            select="local-name(.//green/parent::*)"/>
        <xsl:copy>
            <xsl:copy-of 
                select=".//*[local-name()=$colors_parent]/*[not(self::green)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

我还排除了所有可能的文本元素。如果你想保留“GOOD TEXT”文本节点,目前还不清楚。但是,现在应该很容易使变换适应新的要求。例如,如果您想在 colors 元素下保留任何文本节点,您可以更改使用此变换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/mydoc/file/colors">
        <xsl:variable name="colors_parent"
            select="local-name(.//green/parent::*)"/>
        <xsl:copy>
            <xsl:copy-of 
                select=".//*[local-name()=$colors_parent]/*[not(self::green)]
                      | .//text()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

使用身份规则(它复制嵌套元素)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="mydoc">
        <xsl:apply-templates select="file/colors"/>
    </xsl:template>

    <xsl:template match="green"/>

</xsl:stylesheet>

答案 1 :(得分:1)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>

    <xsl:template match="/">
        <colors>
            <xsl:apply-templates select="//colors/*[not(self::green)]"/>
        </colors>
    </xsl:template>

    <xsl:template match="*">
        <xsl:copy-of select="."/>
    </xsl:template>

</xsl:stylesheet>

输出:

<colors>
    <blue />
    <red />
</colors>