为什么简单的XPATH无法工作

4

我有一个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>

我想获取Parameters中唯一参数的值。问题是为什么这样的语句

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)

给我什么都没有?有没有办法不用创建这样的名称空间怪物语句?

我在这里和你一起。为什么我要在BizTalk中处理所有这些本地名称和命名空间,真是让人头疼啊!你找到解决方法了吗? - peter n
5个回答

2

根据你的XPath实现,你可以使用快捷方式注册XML名称空间,以便你可以像这样编写XPath表达式(假设你已将http1注册为h1,将http2注册为h2)。

string(/h1:Provide/h1:providerRequest/h2:Parameters[1]/h2:Parameter/h2:Name)

如何在BizTalk编排中注册命名空间? - javros
抱歉,我不知道那个...也许你应该适当地给问题打上标签。[tag:xml]和[tag:xpath]太泛泛了。 - Stefan Gehrig

1
只需在XSLT文档中声明命名空间,然后您就可以使用:
string(/ns0:Provide/ns0:providerRequest/ns1:Parameters[1]/ns1:Parameter/ns1:Name)

仅仅通过查看本地名称,您实际上完全忽略了命名空间 - 那么您为什么首先要添加它们呢?


这是一个由 BizTalk 生成的 XPATH。我不知道它为什么要这样做。 - javros

1

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

  1. 它使单元测试和编辑这些常量更容易;
  2. 它使表达式形状更短,更容易阅读。

这并不能解决长XPath的问题,尽管您可以始终使用String.Format()使它们更易读。但是,它确实具有上述优点...


0

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

Biztalk通过使用命名空间不可知的xpath来避免使用XmlNamespaceManager,正如您所注意到的那样,这种方法相当冗长(但是它是生成的,并且通常被隐藏起来)。

如果您确信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导航的性能问题。


0

我知道这已经过了一段时间,但对我有用的方法是在xpath中不引用包含命名空间的根节点,然后它就可以干净地工作(例如//Parameter[1])。但是似乎每个节点上都有命名空间,因此,如果在架构中只限定根而不是所有节点,那么这将有所帮助。 xpath中混合命名空间会让BizTalk感到不满意。希望这能帮助某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接