xsl:带和不带命名空间的模板匹配行为

时间:2016-08-12 21:09:42

标签: xslt xml-namespaces

我正在尝试使用apache fop格式化PDF报告,我发现了一种我无法理解的行为。

在尝试调试问题时,我将其跟踪到xsl:template match指令的xsl行为,在xml文件中声明和不声明名称空间。

即使我使用另一个implmentation(xsltproc),xsl的行为也是一样的,所以差异应该在xsl规范中,它与apache fop无关,但是我无法找到解释,所以我会如果有人可以帮助我,我会非常感激。

这是代码。首先是“bugger.xml”文件:

<?xml version="1.0" encoding="UTF-8" ?>
<parent xmlns="http://www.bugger.org">parent_value</parent>

这是“bugger.xsl”文件:

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

<xsl:template match="/">
    OK, root element matches...
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="/*">
    you WILL see this writing... I'm a parent tag, look: I'm a "<xsl:value-of select="name()"/>", why you cannot see me in the /parent template match?
    The naming match fails because of the xmlns directive in the bugger.xml file. If you remove it, all works fine.
</xsl:template>

<xsl:template match="/parent">
    you will NOT see this writing, while you should see it...
</xsl:template>

</xsl:stylesheet>

问题是:为什么如果我放置xmlns =“http://www.bugger.org”指令,xsl:template匹配“/ *”,如果我删除它,xsl:template匹配“ / parent“?

感谢您的帮助!!!

2 个答案:

答案 0 :(得分:1)

当你的来源是:

<?xml version="1.0" encoding="UTF-8" ?>
<parent xmlns="http://www.bugger.org">parent_value</parent>

这个模板:

<xsl:template match="/parent">
    you will NOT see this writing, while you should see it...
</xsl:template>

与源XML文件中的任何内容都不匹配,也不会应用。 OTOH,这个模板:

<xsl:template match="/*">
    you WILL see this writing... I'm a parent tag, look: I'm a "<xsl:value-of select="name()"/>", why you cannot see me in the /parent template match?
    The naming match fails because of the xmlns directive in the bugger.xml file. If you remove it, all works fine.
</xsl:template>

与根元素匹配(在此示例中本地名称parent),因此将应用于该元素。

现在,当你的来源是:

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

然后两个模板都匹配根parent元素 - 并且具有相同的优先级(0.5)。在这种情况下,处理器将选择最后一个匹配模板 - 请参阅:https://www.w3.org/TR/xslt/#conflict

注意

  1. /是根节点,而不是根元素

  2. &#34; xmlns =&#34; http://www.bugger.org"指令&#34;被称为名称空间声明 - 建议您更多地了解XML中的名称空间以及如何在XSLT中处理它们。

答案 1 :(得分:1)

使用:

"Uncaught SyntaxError: Unexpected token :"

您已将“默认命名空间”设置为“http://www.bugger.org”命名空间URI。见https://www.w3.org/TR/REC-xml-names/#defaulting

XSLT处理器(以及实现处理XML的REC-xml名称的任何其他内容)将'parent'元素视为'in'(非技术术语)'http://www.bugger.org'命名空间。< / p>

在样式表中,<parent xmlns="http://www.bugger.org">parent_value</parent> 匹配,因为/*(在此上下文中)匹配所有元素。 *不匹配,因为它只匹配带有空名称空间URI的/parent(这就是删除名称空间声明时匹配的原因)。见https://www.w3.org/TR/xpath/#node-tests

(另外,在您展示的样式表中,您不需要匹配模式中的前导parent。)

要在/上专门匹配“http://www.bugger.org”命名空间URI,您需要匹配元素的“限定名称”(QName)。即,您需要在匹配模式中使用带有parent的名称空间前缀,即使您可以使用与源XML中的默认名称空间相同的名称空间URI(因为在XSLT中,模式中的非限定名称始终位于null namespace):

parent