输入XML的动态命名空间

时间:2016-01-13 11:32:47

标签: xslt xpath namespaces

我搜索了许多关于动态设置命名空间的帖子,但它们似乎都指的是设置输出XML的命名空间。

我遇到的问题是输入XML的命名空间(在root中定义,所有子节点都相同),并且相同的样式表需要能够处理这两个输入。

例如,一个输入XML是:

<root xmlns="aaa">
    <body>xxx</body>
</root>

另一个输入XML是:

<root xmlns="bbb">
    <body>yyy</body>
</root>

在样式表中,我的XPath显然需要使用定义的命名空间,该命名空间用前缀声明,即:。

xmlns:one="aaa"

但是,只要第二个输入XML被转换,它当然就无法工作。

我可以定义另一个名称空间,例如

xmlns:two="bbb"

但是在正确的时间使用该命名空间的唯一方法是复制所有XSLT代码并将其他命名空间作为所有XPath的前缀(即使那时我仍然需要确定要使用哪个XPath集合可能很有趣..)

我的样式表目前使用以下XPath:

%lt;SOMETHING&gt;
<xsl:value-of select="one:body" />
%lt;/SOMETHING&gt;

如您所见,它使用“one”命名空间前缀。有没有办法只获取“body”标签的值,无论命名空间如何?正如下面的评论中提到的,虽然我很欣赏它们是基于命名空间的不同元素,但我知道每个元素中的信息都是相同的,所以我可以将它们视为这样。

我看过有关使用带有命名空间属性的xsl:element的帖子,但我可以告诉他们只定义输出XML的命名空间,而不是输入。 (更糟糕的是,我输出的内容实际上是转义的XML,例如%lt; SOMETHING&gt;所以我无法使用xsl:element)。

我目前的解决方案(自发布此内容)是在主样式表中包含两个额外的样式表。每个特定于命名空间“one”或命名空间“two”,XPath的每一行都使用相关的命名空间前缀。

我希望有一种方法可以避免使用两个单独的样式表,除了名称空间前缀之外几乎完全相同。

提前致谢。

3 个答案:

答案 0 :(得分:2)

如果我说得对,你想要处理XML忽略元素&#39;命名空间。实际上,命名空间的意义在于区分来自不同上下文的元素。因此,从XML的角度来看,<one:body><two:body>完全无关,除了它们碰巧具有相同的名称。

无论如何你想要这样做,而不是:

<xsl:template match="one:body">
<xsl:template match="two:body">

你应该匹配元素&#39;仅限本地名称:

<xsl:template match="*[local-name()='body']">

为了给出更多背景:如果你说

<xsl:template match="one:body">

那么这只是

的简短表示法
<xsl:template match="*[namespace-uri()='aaa'][local-name()='body']">

(即&#34; 匹配名称空间为&#39; aaa&#39;且名称为&#39; body&#39; &#34;)

因此,通过遗漏

来忽略命名空间
[namespace-uri()='aaa']

成功

<xsl:template match="*[local-name()='body']">

相反,你最好说

<xsl:template match="*[namespace-uri()='aaa' or namespace-uri()='bbb'][local-name()='body']">

<xsl:template match="*[namespace-uri()='aaa' or namespace-uri()='bbb' or namespace-uri()='ccc'][local-name()='body']">

等等。 如果,正如dret所说,您事先知道所有可能的名称空间。

答案 1 :(得分:1)

我建议您定义两个名称空间,然后使用以下路径:

<xsl:value-of select="one:body" />

解决源XML中的元素。

例如,而不是:

<xsl:value-of select="one:body | two:body" />

使用:

<script type="text/javascript" id="AssetJS"></script>

答案 2 :(得分:0)

正如我已经写过的那样!而不是

<xsl:value-of select="one:body" />

你可以写

<xsl:value-of select="*[local-name()='body']" />

或者,如果你有XPath 2.0,那么

<xsl:value-of select="*:body" />