如何使用Nokogiri在XSL中定位命名空间的XML属性?

时间:2014-08-06 13:39:25

标签: ruby-on-rails xml xslt xpath nokogiri

假设我的XML部分看起来像这样:

... lorem ipsum dolor sit amet, <ext-link href="http://www.consectetur.org/">consectetur</ext-link> adipiscing elit ... 

我可以很容易地使用

在XSD中定位该网址
<xsl:template match="ext-link">
    <a href="{@href}"><xsl:apply-templates/></a>
</xsl:template>

但是当我的XML看起来像这样时,我不知所措:

... lorem ipsum dolor sit amet, <ext-link xlink:href="http://www.consectetur.org/">consectetur</ext-link> adipiscing elit ...

这不起作用:

<xsl:template match="ext-link">
    <a href="{@xlink:href}"><xsl:apply-templates/></a>
</xsl:template>

@xlink@href都没有。我在这里缺少哪些重要的XML / XSL知识?

更新

由于我使用Nokogiri进行解析,我可能遗漏的是如何告诉它关联命名空间 - 我不知道在哪里这样做。我像这样拉入XML和XSL

doc = Nokogiri::XML(File.read('/some/xml/path'))
xslt = Nokogiri::XML(File.read('/some/xsl/path'))

result = xslt.transform(doc)

使用此功能,我的XML中的所有{@xlink}{@href}{@xlink:href}都不会在结果中显示任何内容。

2 个答案:

答案 0 :(得分:1)

源XML文档将在树的更高位置声明名称空间,假设这是标准的XLink机制

xmlns:xlink="http://www.w3.org/1999/xlink"

为了引用具有本地名称href和名称空间URI http://www.w3.org/1999/xlink的属性,您需要将相同的名称空间URI绑定到样式表中的前缀 ,然后在XPath表达式中使用此前缀。 E.g。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="..."
                xmlns:xlink="http://www.w3.org/1999/xlink">

  <xsl:template match="ext-link">
    <a href="{@xlink:href}"><xsl:apply-templates/></a>
  </xsl:template>

</xsl:stylesheet>

在这种情况下,xlink是该URI的传统前缀,但通常前缀不必与使用的源文档相同,重要的是它映射到正确的URI 。这也可行:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="..."
                xmlns:xl="http://www.w3.org/1999/xlink">

  <xsl:template match="ext-link">
    <a href="{@xl:href}"><xsl:apply-templates/></a>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

如果 source 文档没有使用名称空间(可能已经以某种方式删除了声明),那么您需要选择没有名称空间的属性和“本地”名称xlink:href。这对XPath来说有点棘手,因为它会将:解释为分隔命名空间,但你可以使用name() function这样做:

<xsl:template match="ext-link">
  <a href="{@*[name() = 'xlink:href']}"><xsl:apply-templates/></a>
</xsl:template>