如何获取具有不同命名空间的元素

时间:2014-08-11 07:30:06

标签: xml xpath xquery

我希望得到以下xml的元素名称。 我的请求中的问题是我想获得Payload元素。为此,我使用了这个表达式

name(//env:Payload)

所以我得到了这个结果环境:有效载荷

<env:requeset xmlns:env="http://eai.ssss.xxx/Envelope" xmlns:ggg="http://fai.dgn.sss/ggg">
<env:clientbody>
<env:Payload>
<ggg:Service>
<ggg:Request>
<a>name</a>
<b>age</b>
<c>address</c>
</ggg:Request>
</ggg:Service>
</env:Payload>
</env:clientbody>
</env:requeset>

但有时我的客户端发送的请求包含不同的元素,有时也没有命名空间。那么我如何得到以下要求呢

<requeset xmlns:="http://eai.ssss.xxx/Envelope" xmlns:ggg="http://fai.dgn.sss/ggg">
<clientbody>
<Payload>
<ggg:Service>
<ggg:Request>
<a>name</a>
<b>age</b>
<c>address</c>
</ggg:Request>
</ggg:Service>
</Payload>
</clientbody>
</requeset>

对于上面的请求,我使用相同的表达式,因此它给出了错误,所以如何在2种情况下获得Payload元素或任何情况。 我试过这个,但它不起作用

name(//( local-name()='Payload'))

给予ERROR - Failed to evaluate XPath expression: A location step was expected following the '/' or '//' token.

所以请指导获取没有命名空间和不同命名空间的元素我也尝试使用Contains表达式,但我无法得到它。

2 个答案:

答案 0 :(得分:2)

如错误消息所示,您编写的语法不正确。如果要比较每个元素的本地名称,可以这样做:

//*(local-name() = 'Payload')

但是等等,有更好的选择来实现这一目标。你在这里做的基本上是忽略命名空间。您还可以使用通配符名称空间运算符*以更清晰的语法实现此目的。它就像

一样简单
//*:Payload

如果您仍想要尊重命名空间,还可以使用union运算符|合并两个结果。这样,您可以获得带有env名称空间且没有任何名称空间的Payload元素:

//env:Payload | //Payload

当然,在所有这些情况下,您都可以使用name()来获取元素名称。

答案 1 :(得分:2)

您误解了数据和问题;因此,您提出的问题与您的情况无关。

您没有任何具有不同命名空间的元素。您显示的两个请求都包含扩展名为{http://eai.ssss.xxx/Envelope} Payload的元素;它们的区别仅在于为该命名空间使用不同的前缀(env与没有前缀)。同样的查询应该适用于两者;一个简单的演示是:

declare namespace e = "http://eai.ssss.xxx/Envelope";

let $testdata := <data>
  <env:requeset xmlns:env="http://eai.ssss.xxx/Envelope" 
                xmlns:ggg="http://fai.dgn.sss/ggg">
    <env:clientbody>
      <env:Payload>
        ...
      </env:Payload>
    </env:clientbody>
  </env:requeset>
  <requeset xmlns="http://eai.ssss.xxx/Envelope"
            xmlns:ggg="http://fai.dgn.sss/ggg">
    <clientbody>
      <Payload>
        ...
      </Payload>
    </clientbody>
  </requeset>
</data>

return $testdata//e:Payload

如果您尝试这样做,您会看到它返回两个元素,而不仅仅是一个元素。

如果第二个示例输入遇到问题,可能是因为字符串xmlns:不是命名空间声明的合法名称。将xmlns:="http://eai.ssss.xxx/Envelope"更改为xmlns="http://eai.ssss.xxx/Envelope"