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>