xsl:template 匹配有和没有命名空间的行为
xsl:template match behaviour with and without namespace
我在尝试使用 apache fop 格式化 PDF 报告时发现了一个我无法理解的行为。
在尝试调试问题时,我将其追溯到 xsl:template 匹配指令的 xsl 行为,在 xml 文件中声明了和不声明了命名空间。
即使我使用另一个实现 (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” ?
感谢您的帮助!!!
当您的来源是:
<?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
注:
/
是根节点,不是根元素.
“xmlns="http://www.bugger.org" 指令”被称为 命名空间声明 - 而你'建议您在 XML 中了解有关名称空间的更多信息以及如何在 XSLT 中处理它们。
与:
<parent xmlns="http://www.bugger.org">parent_value</parent>
您已将 'default namespace' 设置为 'http://www.bugger.org' namespace URI. See https://www.w3.org/TR/REC-xml-names/#defaulting
XSLT 处理器(以及任何其他实现处理您的 XML 的 REC-xml 名称的处理器)将 'parent' 元素视为 'in'(不是技术术语)“http://www.bugger.org”命名空间。
在您的样式表中,/*
匹配,因为 *
(在此上下文中)匹配所有元素。 /parent
不匹配,因为它只匹配具有空名称空间 URI 的 parent
(这就是为什么它在您删除名称空间声明时匹配)。参见 https://www.w3.org/TR/xpath/#node-tests
(此外,在您显示的样式表中,您的匹配模式中不需要前导 /
。)
要专门匹配具有“http://www.bugger.org”名称空间 URI 的 parent
,您需要匹配元素的 'qualified name' (QName)。即,您需要在匹配模式中使用带 parent
的名称空间前缀,即使您可以使用与源 XML 中的默认名称空间相同的名称空间 URI(因为在 XSLT 中,模式中的非限定名称总是在 null 命名空间中):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:b="http://www.bugger.org"
version="1.0"
exclude-result-prefixes="b">
<xsl:template match="b:*">
you will NOT see this writing, because it has a lower priority...
</xsl:template>
<xsl:template match="b:parent">
you will see this writing.
</xsl:template>
</xsl:stylesheet>
我在尝试使用 apache fop 格式化 PDF 报告时发现了一个我无法理解的行为。
在尝试调试问题时,我将其追溯到 xsl:template 匹配指令的 xsl 行为,在 xml 文件中声明了和不声明了命名空间。
即使我使用另一个实现 (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” ?
感谢您的帮助!!!
当您的来源是:
<?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
注:
/
是根节点,不是根元素.“xmlns="http://www.bugger.org" 指令”被称为 命名空间声明 - 而你'建议您在 XML 中了解有关名称空间的更多信息以及如何在 XSLT 中处理它们。
与:
<parent xmlns="http://www.bugger.org">parent_value</parent>
您已将 'default namespace' 设置为 'http://www.bugger.org' namespace URI. See https://www.w3.org/TR/REC-xml-names/#defaulting
XSLT 处理器(以及任何其他实现处理您的 XML 的 REC-xml 名称的处理器)将 'parent' 元素视为 'in'(不是技术术语)“http://www.bugger.org”命名空间。
在您的样式表中,/*
匹配,因为 *
(在此上下文中)匹配所有元素。 /parent
不匹配,因为它只匹配具有空名称空间 URI 的 parent
(这就是为什么它在您删除名称空间声明时匹配)。参见 https://www.w3.org/TR/xpath/#node-tests
(此外,在您显示的样式表中,您的匹配模式中不需要前导 /
。)
要专门匹配具有“http://www.bugger.org”名称空间 URI 的 parent
,您需要匹配元素的 'qualified name' (QName)。即,您需要在匹配模式中使用带 parent
的名称空间前缀,即使您可以使用与源 XML 中的默认名称空间相同的名称空间 URI(因为在 XSLT 中,模式中的非限定名称总是在 null 命名空间中):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:b="http://www.bugger.org"
version="1.0"
exclude-result-prefixes="b">
<xsl:template match="b:*">
you will NOT see this writing, because it has a lower priority...
</xsl:template>
<xsl:template match="b:parent">
you will see this writing.
</xsl:template>
</xsl:stylesheet>