在 xsl 转换期间匹配名称空间
Matching on namespace during xsl transform
我有一个文档,其根元素定义了一个命名空间,当我编写 xsl 进行转换时,我没有看到任何匹配的元素。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//supplydetail/price"/>
</xsl:stylesheet>
XML 文件如下所示:
<?xml version="1.0" encoding="iso-8859-1"?>
<ONIXmessage xmlns="http://www.editeur.org/onix/2.1/short">
<header>
<m173>2012086</m173>
<m174>foobar</m174>
</header>
<product>
<supplydetail>
<j137>Foo Bar</j137>
<j396>20</j396>
<price>
<j148>42</j148>
<j151>5.99</j151>
<j152>AUD</j152>
<b251>AU</b251>
</price>
</supplydetail>
</product>
</ONIXmessage>
我看到的是我的 supplydetail/price
元素根本不匹配,即使它存在于 /ONIXmessage/product/supplydetail/price
的文档中
我也尝试在 xsl 中指定从根目录开始的完整路径,但也没有用。我得到的输出是输入的直接副本,我期望的是除了价格元素之外的输入副本。我认为原因是输入 XML 的 ONIXmessage 元素中的命名空间声明,但我如何在 xsl.xml 中指定它?
谢谢
我同意这个问题经常被问到,但我不同意再问一次是错误的。您可能已经尝试找到解决方案,但未能理解或应用您找到的内容。
可以在 Understanding XML Namespaces and Namespaces in XSLT 上找到关于该主题的从入门到深入的优秀论文,均由 Evan Lenz 撰写。如果您想对 XML 和 XSLT 做任何有用的事情,我真的建议您花点时间阅读这篇文章。
底线是:在 XSLT 中声明名称空间,通常在顶部 xsl:stylesheet
元素并在您的 XPath 表达式中使用这些名称空间:
<xsl:stylesheet version="2.0"
xmlns:onix="http://www.editeur.org/onix/2.1/short"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//onix:supplydetail/onix:price"/>
</xsl:stylesheet>
由于您使用的是 XSLT 2.0,因此使用 xpath-default-namespace
就足够了,它设置了用于 XPath 表达式和模式中的无前缀节点测试的名称空间:
<xsl:stylesheet version="2.0"
xpath-default-namespace="http://www.editeur.org/onix/2.1/short"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
要获得用于文字结果元素的相同命名空间,请在这些名称前加上声明的命名空间,或将默认命名空间设置为指向您选择的命名空间(在您当前的代码中,没有文字结果元素)。
如果您事先不知道实际的命名空间,但知道本地名称,请使用 *:supplydetail
之类的匹配模式,但这也存在匹配另一个命名空间中的相同名称的风险;如果你能避免它,你应该。
我有一个文档,其根元素定义了一个命名空间,当我编写 xsl 进行转换时,我没有看到任何匹配的元素。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//supplydetail/price"/>
</xsl:stylesheet>
XML 文件如下所示:
<?xml version="1.0" encoding="iso-8859-1"?>
<ONIXmessage xmlns="http://www.editeur.org/onix/2.1/short">
<header>
<m173>2012086</m173>
<m174>foobar</m174>
</header>
<product>
<supplydetail>
<j137>Foo Bar</j137>
<j396>20</j396>
<price>
<j148>42</j148>
<j151>5.99</j151>
<j152>AUD</j152>
<b251>AU</b251>
</price>
</supplydetail>
</product>
</ONIXmessage>
我看到的是我的 supplydetail/price
元素根本不匹配,即使它存在于 /ONIXmessage/product/supplydetail/price
我也尝试在 xsl 中指定从根目录开始的完整路径,但也没有用。我得到的输出是输入的直接副本,我期望的是除了价格元素之外的输入副本。我认为原因是输入 XML 的 ONIXmessage 元素中的命名空间声明,但我如何在 xsl.xml 中指定它?
谢谢
我同意
可以在 Understanding XML Namespaces and Namespaces in XSLT 上找到关于该主题的从入门到深入的优秀论文,均由 Evan Lenz 撰写。如果您想对 XML 和 XSLT 做任何有用的事情,我真的建议您花点时间阅读这篇文章。
底线是:在 XSLT 中声明名称空间,通常在顶部 xsl:stylesheet
元素并在您的 XPath 表达式中使用这些名称空间:
<xsl:stylesheet version="2.0"
xmlns:onix="http://www.editeur.org/onix/2.1/short"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//onix:supplydetail/onix:price"/>
</xsl:stylesheet>
由于您使用的是 XSLT 2.0,因此使用 xpath-default-namespace
就足够了,它设置了用于 XPath 表达式和模式中的无前缀节点测试的名称空间:
<xsl:stylesheet version="2.0"
xpath-default-namespace="http://www.editeur.org/onix/2.1/short"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
要获得用于文字结果元素的相同命名空间,请在这些名称前加上声明的命名空间,或将默认命名空间设置为指向您选择的命名空间(在您当前的代码中,没有文字结果元素)。
如果您事先不知道实际的命名空间,但知道本地名称,请使用 *:supplydetail
之类的匹配模式,但这也存在匹配另一个命名空间中的相同名称的风险;如果你能避免它,你应该。