match元素和属性,如果元素属于非默认命名空间

时间:2012-10-31 15:45:48

标签: xml xslt

我想用名称" FOO"修改元素的属性值,所以我写道:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
      <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="FOO/@extent">
      <xsl:attribute name="extent">
      <xsl:text>1.5cm</xsl:text>
      </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

这个东西有效。现在我需要同样的东西,但是元素&#34; fs:BOO&#34;。 我尝试用&#34; fs:BOO&#34;替换FOO,但是xsltproc说它无法编译 这样的代码。我以这种方式暂时解决了这个问题:

sed 's|fs:BOO|fs_BOO|g' | xsltproc stylesheet.xsl - | sed 's|fs_BOO|fs:BOO|g'

但可能有更简单的解决方案,没有使用&#34; sed&#34;?

输入数据示例:

<root>
    <fs:BOO extent="0mm" />
</root>

如果写:

<xsl:template match="fs:BOO/@extent">

我得到了:

xsltCompileStepPattern : no namespace bound to prefix fs
compilation error: file test.xsl line 10 element template
xsltCompilePattern : failed to compile 'fs:BOO/@extent'

1 个答案:

答案 0 :(得分:1)

首先,我希望您的XML具有命名空间的声明,否则它将无效

<root xmlns:fs="www.foo.com">
    <fs:BOO extent="0mm" />
</root>

这也适用于您的XSLT。如果您尝试执行<xsl:template match="fs:BOO/@extent">,那么您还需要在XSLT中对命名空间进行声明。

<xsl:stylesheet version="1.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:fs="www.foo.com">

重要的是命名空间URI与XML中的名称匹配。

但是,如果您想要处理不同的命名空间,则可以采用不同的方法。您可以使用 local-name()函数来检查没有名称空间前缀的元素的名称。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
      <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="*[local-name()='BOO']/@extent">
      <xsl:attribute name="extent">
         <xsl:text>1.5cm</xsl:text>
      </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

这应输出以下内容

<root xmlns:fs="fs">
   <fs:BOO extent="1.5cm"></fs:BOO>
</root>