开发者

xsl: transform namespaced tags

开发者 https://www.devze.com 2023-04-10 20:52 出处:网络
I have an xsl that copies a xml file and renames the root tag. <?xml version=\"1.0\" encoding=\"UTF-8\"?>

I have an xsl that copies a xml file and renames the root tag.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:abc="http://example.com">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

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

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

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

</xsl:stylesheet>

That works fine but when I uncomment the last block to handle some namespaced tags I got an er开发者_开发问答ror that the says that something is wrong with the copy statement. How can I match and transform namespaced tags?


You are likely getting an error because the abc:set element has attributes, and your template matching on abc:set is producing "naked" attributes that are not attached to an element.

Since you are not copying the abc:set element (or creating an element) in the template match for abc:set, when the apply-templates inside of that template applies the templates to the selected abc:set/@* and abc:set/node(), then the attributes match the identity template and will be copied forward.

You can verify whether that is the issue by taking the @* out of the select statement for the apply-templates, like this:

<xsl:template match="abc:set">
    <xsl:apply-templates select="node()"/>
</xsl:template>

The template above will only process the child nodes of abc:set.

If your intent was to simply copy the abc:set, then you don't need a specific template matching on that element. The identity template will match on it and handle that for you.


I don't know what exactly you are trying to achieve. Your question is a little abstract. However your match attribute is correct. But there is not difference right now as to what :

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

does and as to what this :

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

does. If you just want to copy everything then the first template would suffice including tags with namespaces. Otherwise I guess you would need to do something differently when matching your namespaced tag. If so then you don't need to call the identity match template again. e.g. :

<!--Do something with abc:set-->
<xsl:template match="abc:set">
    <setchanged name="{@name}"/>
</xsl:template>

Rest assured that this will match all abc:set tags and apply the transformation to them.


If you really want to remove the abc:set element but keep the sub-tree of which it is the root of, then replace:

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

with:

<xsl:template match="abc:set">
    <xsl:apply-templates/>     
</xsl:template>

Your original code would cause errors if the matched element has attributes, because then the identity rule will copy them, likely not in addition to creating an element, so this would be an attempt at producing attributes belonging to no element. Any XSLT processor is obliged to signal an error in this case.

The replacement code doesn't process any of the attributes of the matched abc:set element.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号