xsl 只递归复制一些元素并删除一些后代 [英] xsl to only copy some elements recursively and remove some of the descendants

查看:44
本文介绍了xsl 只递归复制一些元素并删除一些后代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想变身

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

用简单的英语,我想递归地复制颜色元素,包括文本,忽略 XML 文档的其余部分并丢弃绿色元素.

In plain english, I would like to copy the colors element recursively, including text, ignore the rest of the XML document and discard the green element.

有一些解决方案适用于上述示例,但如果 XML 稍有不同,则会失败.例如,通过在 color 元素下添加 nest 元素,或者在 color<的层次结构中添加 other 元素/strong> 元素,或在 color 元素范围内的文本 (GOOD TEXT) 和另一个超出其范围 (BAD TEXT) 的文本.

There are solutions working with the example above but will fail if the XML varies even slightly. For instance by adding the nest element under the color element, or the other element which is not in the hierarchy of the color element, or text that is in the scope of the color element ( GOOD TEXT ) and another that is outside its scope ( 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>

我最感兴趣的是通用的解决方案,而不是针对此处提供的示例进行定制.

I am most interested in a solution that is generic and not customized to the exemples presented here.

推荐答案

这个新的变换足够通用,可以复制颜色元素无论它们的父元素是什么.

This new transform is general enough to copy colors elements whatever their parent is.

<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 元素下保留任何文本节点,您可以更改使用此转换:

I've also excluded all possible text elements. It's not still clear if you want to keep the "GOOD TEXT" text node. However it should be very easy for you now to adapt the transform to new requirements. For example if you want to keep any text node under colors element you can change use this transform:

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

<小时>

身份规则的使用(它复制nest元素)

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

这篇关于xsl 只递归复制一些元素并删除一些后代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆