Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml xsl仅递归复制某些元素并删除某些子体_Xml_Xslt_Xpath - Fatal编程技术网

Xml xsl仅递归复制某些元素并删除某些子体

Xml xsl仅递归复制某些元素并删除某些子体,xml,xslt,xpath,Xml,Xslt,Xpath,我想转型 <?xml version="1.0" ?> <mydoc> <file> <colors> <blue /> <red /> <green /> </colors> <secret> <username />

我想转型

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

进入


在纯英语中,我希望递归地复制colors元素,包括文本,忽略XML文档的其余部分,并丢弃绿色元素

有一些解决方案可以使用上面的示例,但是如果XML的变化很小,就会失败。例如,通过在color元素下添加nest元素,或不在color元素层次结构中的其他元素,或在color元素范围内的文本(好文本)和另一个超出其范围的文本(坏文本)


好文章
错误文本
错误文本2
我最感兴趣的是一个通用的解决方案,而不是根据此处提供的示例进行定制。


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

这个新的转换足够通用,可以复制颜色元素,不管它们的父元素是什么

<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”文本节点。然而,您现在应该很容易适应新需求的转换。例如,如果要将任何文本节点保留在颜色元素下,则可以使用此变换进行更改:

<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="/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>
<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>