在xsl转换期间匹配命名空间

时间:2015-09-02 19:54:26

标签: xslt xpath xml-namespaces onix

我有一个文件,根元素定义了一个命名空间,当我写一个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中指定root的完整路径,并且din也工作。我得到的输出是输入的直接副本,我期待的是除了price元素之外的输入副本。我认为原因是输入XML的ONIXmessage元素中的名称空间声明,但是如何在xsl中指定它。

由于

1 个答案:

答案 0 :(得分:1)

我同意Matthias Müller这个问题经常被问到,但我不同意再次提出这个问题是不对的。您可能已经尝试找到解决方案,但未能理解或应用您找到的内容。

Understanding XML NamespacesNamespaces 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,但这也有可能在另一个命名空间中匹配相同的名称;如果你可以避免它,你应该。