3

当根元素具有默认命名空间属性而不是没有默认命名空间属性时,我遇到了 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>

添加

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

4

2 回答 2

5

这是 XPath/XSLT 中最常见的问题

XPath 将无前缀的元素名称视为属于“无命名空间”。

W3C Xpath规范

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

因此,在具有默认命名空间的文档中,对具有无前缀名称(例如“someName”)的元素的引用不会选择任何内容,因为 XML 文档中的“无命名空间”中没有任何元素,而是someName意味着具有名称“ someName”,属于“无命名空间”。

解决方案

如果我们想按名称选择一个元素,我们必须为该名称添加前缀,并且该前缀必须与默认命名空间相关联。

这种转变

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

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

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

产生想要的正确结果

<root>
   <w>x</w>
</root>
于 2012-04-14T21:21:02.200 回答
2

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

于 2012-04-14T21:04:42.433 回答