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

时间:2017-02-28 15:51:54

标签: 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

1 个答案:

答案 0 :(得分:3)

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

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

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

你能做什么,只需改变你的模板匹配&#34; Cups | Cups // *&#34;改为使用xsl:copy-of ......

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

但是,看起来你真正想要做的是实际删除Batteries节点及其后代。如果是这样,请使用身份模板复制其他所有内容,并使用单个模板忽略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除外。