迭代具有在XSL中声明的xmlns属性的XML节点

时间:2010-01-25 18:39:56

标签: xml loops xslt foreach xml-namespaces

我正在创建一个XSL来格式化我正在集成的API中的一些传入XML。我收到的xml看起来像:

<items>
  <item xmlns="http://www.tempuri.org/Item.xsd">
    <key>value</key>
  </item>
  <item>
    <key>value</key>
  </item>
  <item xmlns="http://www.tempuri.org/Item.xsd">
    <key>value</key>
  </item>
</items>

某些“item”节点定义了“xmlns”属性,而其他节点则没有。当我尝试在我的XSL中迭代结果时,它没有找到定义了xmlns属性的节点。

<xsl:for-each select="item">
  <xsl:value-of select="key" />
</xsl:for-each>

我对整个XSL事情都不熟悉,所以我不确定我做错了什么。

2 个答案:

答案 0 :(得分:1)

您需要在<xsl:stylesheet>定义中定义相同的命名空间。

然后:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://www.tempuri.org/Item.xsd"
    extension-element-prefixes="exsl"
    encoding="utf-8">

. . .

<xsl:for-each select="item|ns:item">
    <xsl:value-of select="key|ns:key"/>
</xsl:for-each>

实际上你应该尝试使用相同的命名空间来实现相同的东西。

答案 1 :(得分:0)

首先,如果您不了解XML命名空间的工作原理及其含义,那么您将无法解决问题。你正在努力解决的这个问题是冰山一角。

也就是说,您可以像Kyle Butt建议的那样处理命名空间,在stylesheet元素中为前缀分配转换范围的映射,然后在XPath表达式中使用前缀。

但是如果你不知道命名空间怎么办?然后你必须使用一个更直率的工具:

<xsl:for-each select="*[local-name()='item']">
  <xsl:value-of select="*[local-name()='key']"/>
</xsl:for-each>

使用local-name()完全忽略名称空间。但是您不能在节点测试中使用它(必须是foo之类的名称或像x:foo这样的限定名称),您只能在谓词中使用它。这就是为什么不可爱的*[local-name()='foo']是唯一的方法。