Странность с XDocument, XPath и пространствами имен - PullRequest
11 голосов
/ 15 сентября 2010

У меня есть XML-документ, который выглядит следующим образом:

<kmsg xmlns="http://url1" xmlns:env="url1" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://location that does not exist.xsd">
<header>
    <env:envelope>
        <env:source branch="907" machine="0" password="J123"/>
    </env:envelope>
</header>
<body>
    <OrderResponse xmlns="urn:schemasbasdaorg:2000:orderResponse:xdr:3.01">
        <SomeMoreNodes/>
    </OrderResponse>
</body>

У него нет доступных схем, несмотря на указанное пространство имен (я получаю это из внешнего источника, такне иметь контроля).Я анализирую его с помощью XDocument, но продолжаю получать значения NULL для элементов, не входящих в пространство имен env.Я настраиваю XDocument так:

XDocument Source = XDocument.Load("Testfile.xml");

XmlNamespaceManager oManager = new XmlNamespaceManager(new NameTable());
oManager.AddNamespace(String.Empty, "http://xml.kerridge.net/k8msg");
oManager.AddNamespace("env", "http://xml.kerridge.net/k8msgEnvelope");

Затем я пытаюсь получить значения:

? Source.XPathSelectElement ("// kmsg", oManager)

null

? Source.XPathSelectElement ("// header", oManager)

null

? Source.XPathSelectElement ("// env: source", oManager)

Правильно получает узел

Я предполагаю, что это как-то связано с неправильной настройкой менеджера пространства имен, но я не могу понять, как это исправить.Любая помощь будет отличной.

Спасибо

Ответы [ 2 ]

20 голосов
/ 15 сентября 2010

В дополнение к правильному замечанию @ Mads-Hansen у вас есть типичная проблема не определения (непустого) префикса для одного из пространств имен.

Помните : XPath считаетлюбое имя без префикса, которое должно находиться в «пространстве имен».

Поэтому это неправильно :

Source.XPathSelectElement("//kmsg", oManager)

Это выражение XPath хочет выбрать все элементы kmsg, которые являютсяв "no namespace" и он правильно ничего не выбирает, потому что любые элементы kmsg в предоставленном XML-документе находятся в пространстве имен "http://url1", а не в "no namespace".

Для этогоправильно :

oManager.AddNamespace("xxx", "http://url1");      
Source.XPathSelectElement("//xxx:kmsg", oManager)
1 голос
/ 15 сентября 2010

URI пространства имен, объявленные в исходном XML, не совпадают с URI пространства имен, которые вы регистрируете с помощью XmlNamespaceManager.

В исходном XML-коде:

  1. Анонимное пространство имен (без префикса) имеет имя-пространства: http://url1
  2. env Префикс пространства имен имеет namespace-uri: url1

В вашем XmlNamespaceManager вы заявили:

  1. Анонимное пространство имен (без префикса) имеет namespace-uri:http://xml.kerridge.net/k8msg
  2. Префикс пространства имен env имеет namespace-uri: http://xml.kerridge.net/k8msgEnvelope

Значения namespace-uri должны совпадать, в противном случае вы выбираетеразные имена элементов и никогда не получат совпадение.

...