xsl:template match属性:与默认命名空间的关系

时间:2012-04-14 20:33:00

标签: xslt xpath namespaces

当根元素具有默认的命名空间属性时,我遇到了xslt行为的一个特殊区别,而不是。 我想知道为什么会出现这种差异。

XML输入是

<root>
    <content>xxx</content>
</root>

当应用以下转换时

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

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

    <xsl:template match="content">
        <w>x</w>
    </xsl:template>

</xsl:stylesheet>

结果是预期的

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <w>x</w>
</root>

但是当相同的转换应用于

<root xmlns="http://test.com">
    <content>xxx</content>
</root>

结果不同,仅基于默认模板的应用(有效输出文本节点值'xxx'):

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

加成

如果这是这种情况下的预期行为,那么在第二种情况下匹配content元素需要哪个匹配属性值?

2 个答案:

答案 0 :(得分:5)

这是XPath / XSLT中最常见的

XPath将未加前缀的元素名称视为属于“no namespace”。

W3C Xpath specification

  

如果QName没有前缀,则名称空间URI为空。

因此,在具有默认命名空间的文档中,引用具有无前缀名称的元素(例如“someName”)不会选择任何内容,因为XML文档中的“无命名空间”中没有任何元素,但是{{1 }表示名称为“someName”的元素,属于“no namespace”。

解决方案

如果我们想要按名称选择元素,我们必须在该名称前加上前缀,并且前缀必须与默认名称空间相关联。

此转化

someName

应用于提供的具有默认命名空间的XML文档时:

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="http://test.com" exclude-result-prefixes="x">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>

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

        <xsl:template match="x:content">
            <w>x</w>
        </xsl:template>
</xsl:stylesheet>

生成想要的正确结果

<root xmlns="http://test.com">
    <content>xxx</content>
</root>

答案 1 :(得分:2)

那么究竟是什么问题?如果您只是在寻找解释,请参阅以下内容。根据规范,您正在观察的是正确的行为。当你将命名空间放在某个东西上时,解析器基本上将它完全视为一个不同的元素(比同名但没有命名空间的元素)。因此,在第二种情况下,当您说<xsl:template match="content">时,它与XML文件中的<content>元素不匹配,因为它属于http://test.com命名空间(通过命名空间声明)在它的父母)。因此,默认模板将接管。