xml - 复制指定的元素以及子元素和属性

标签 xml xslt

给定以下 XML:

<Products>
    <Batteries>
        <Name Value="Triple A"/>
        <Colour Value="Red"/>
    </Batteries>
    <Cups>
        <Name Value="Mugs"/>
        <Colour Value="Blue"/>
        <Logo>
            <Company Value="Super Clean!"/>
            <Colour Value="Red"/>
        </Logo>
    </Cups>
    <Cups>
        <Name Value="Teacups"/>
        <Colour Value="Orange"/>
        <Handle Value="Dainty"/>
        <Logo>
            <Company Value="Lovely teas"/>
            <Colour Value="Red"/>
        </Logo>
    </Cups>
</Products>

如何复制 Cups 元素及其所有子元素其所有属性? Cups 的后代几乎可以是任何东西(例如,可以添加一个新元素,但我仍然希望复制它),并且它们也可能具有其他属性。

所以在这种情况下我所需的输出是:

<Products>
    <Cups>
        <Name Value="Mugs"/>
        <Colour Value="Blue"/>
        <Logo>
            <Company Value="Super Clean!"/>
            <Colour Value="Red"/>
        </Logo>
    </Cups>
    <Cups>
        <Name Value="Teacups"/>
        <Colour Value="Orange"/>
        <Handle Value="Dainty"/>
        <Logo>
            <Company Value="Lovely teas"/>
            <Colour Value="Red"/>
        </Logo>
    </Cups>
</Products>

经过一番折腾后,我得到了这个:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>
    <xsl:template match="/">
        <Products>
            <xsl:apply-templates/>
        </Products>
    </xsl:template>
    <xsl:template match="Cups|Cups//*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

但它不会将属性复制到输出。

注意:这不是我的 XML,也没有对应的架构,但我确信会有 Cups

最佳答案

问题出在这个模板上......

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

这将忽略所有属性和文本节点(以及其他模板未匹配的元素)。

您可以做的就是简单地将匹配“Cups|Cups//*”的模板更改为使用xsl:copy-of...

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

但是,看起来您真正想要做的实际上是删除 Batteries 节点及其后代。如果是这样,请使用身份模板复制其他所有内容,并仅使用单个模板来忽略电池,就像这样......

尝试这个 XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

    <xsl:template match="Batteries" />
</xsl:stylesheet>

编辑:针对您的评论,如果您希望复制的元素占少数,请尝试这种方法......

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

    <xsl:template match="Products/*" />

    <xsl:template match="Cups|Spoons" priority="2">
        <xsl:call-template name="identity" />
    </xsl:template>
</xsl:stylesheet>

这将删除 Products 下的所有元素,CupsSpoons 除外。

关于xml - 复制指定的元素以及子元素和属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42513226/

相关文章:

Java DOM xml 不能得到 child

java - 如何通过 dom4j 读取和打印 xml 中的外部(未解析的)通用实体声明

python - 从 python 读取 stdout 生成 XML

javascript - Javascript函数调用时需要括号吗?

xml - XSL 查找字符串并从该点开始

javascript - Node JS、Cheerio、获取 XML 版本

java - Android:确定java文件中的点击按钮

xml - 如何计算节点的属性数量?

XSLT 属性联合

html - 跟随兄弟节点与当前 xslt/xpath