为什么简单的XPATH不起作用

时间:2011-09-14 12:39:15

标签: xml xpath biztalk

我有一个XML(在BizTalk中)看起来像

<ns0:Provide xmlns:ns0="http1" xmlns:ns1="http2" xmlns:ns2="http://schemas.microsoft.com/2003/10/Serialization/">
  <ns0:providerRequest>
    <ns1:Header>
      <ns1:Operation>Get_RU_PatchData</ns1:Operation>
      <ns1:RequestId>f6bbeb27-1bfd-4d9c-90e4-d195baf8ca60</ns1:RequestId>
      <ns1:SendDate>2004-02-14T21:44:14</ns1:SendDate>
      <ns1:SenderSystemName>temperat iras</ns1:SenderSystemName>
    </ns1:Header>
    <ns1:Parameters>
      <ns1:Parameter>
        <ns1:Name>turbine corripuit</ns1:Name>
        <ns1:Value>regemque dedit</ns1:Value>
      </ns1:Parameter>
   </ns1:Parameters>
  </ns0:providerRequest>
</ns0:Provide>

我尝试获取参数中唯一参数的值。 问题是为什么这样的声明

string(/*[local-name()='Provide' and namespace-uri()='http1']/*[local-name()='providerRequest' and namespace-uri()='http1']/*[local-name()='Parameters' and namespace-uri()='http2'][1]/*[local-name()='Parameter' and namespace-uri()='http2']/*[local-name()='Name'])

这个

工作正常
string(/Provide/providerRequest/Parameters[1]/Parameter/Name)

什么都没给我?有没有办法不用命名空间创建这种怪异的语句?

5 个答案:

答案 0 :(得分:2)

根据您的XPath实现,您可以使用快捷方式注册XML命名空间,以便您可以像这样编写XPath表达式(假设您将http1注册为h1http2注册为{{ 1}}。

h2

答案 1 :(得分:1)

只需在XSLT文档中声明名称空间,然后就可以使用:

string(/ns0:Provide/ns0:providerRequest/ns1:Parameters[1]/ns1:Parameter/ns1:Name)

通过查看本地名称,您可以有效地忽略命名空间 - 为什么首先添加它们呢?

答案 2 :(得分:1)

我喜欢将所有常量(包括XPath)放在静态类中,然后在我的BizTalk项目中引用它。这有许多优点,包括:

  1. 它使单元测试和编辑这些常量更容易;
  2. 它使表达式形状更短,更容易阅读。
  3. 虽然您总是可以使用String.Format()来提高它们的可读性,但这并不能解决长XPath的问题。但是,它确实具有上述优点......

答案 3 :(得分:0)

我知道这已经有一段时间但是对我来说有用的是不在xpath中引用根节点(包含命名空间),然后它工作干净(例如//参数[1])。但是看起来每个节点上都有名称空间,所以如果不能限定除模式中的根之外的所有节点,这将有所帮助。有一些关于在BizTalk不喜欢的xpath中混合名称空间的东西。希望这有助于某人。

答案 4 :(得分:0)

与BizTalk使用Xpath的方式没有什么不同,例如.NetJava解析器 - 只要xml文档使用名称空间,您就需要在创建引用元素时指定名称空间(或别名)。

Biztalk通过使用XmlNamespaceManager来规避namespace agnostic xpath的需要,正如您所指出的那样,它是相当冗长的(但是又一次,它被生成并且通常隐藏在视线之外)。

如果您确信元素名称在xml中是唯一的,则可以从路径中删除namespace-uri()位,即

string(/*[local-name()='Provide']/*[local-name()='providerRequest']
       /*[local-name()='Parameters'][1]/*[local-name()='Parameter']
       /*[local-name()='Name'])

如果您非常自信关于元素名称的唯一性,您可以缩短路径:

string(//*[local-name()='SomeUniqueElementName']

但要小心 - 对于大型xml文档,我遇到了双斜杠xpath导航的性能问题。