Странность с XDocument, XPath и пространствами имен
У меня есть документ 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)
Gets the node correctly
Я предполагаю, что это связано с неправильной настройкой менеджера пространства имен, но я не могу понять, как это исправить. Любая помощь будет отличной.
Спасибо
Ответы
Ответ 1
В дополнение к правильному замечанию @Mads-Hansen у вас типичная проблема не определять (непустой) префикс для одного из пространств имен.
Помните. XPath считает, что любое неподписанное имя находится в "без пространства имен".
Поэтому это неверно:
Source.XPathSelectElement("//kmsg", oManager)
Это выражение XPath хочет выбрать все kmsg
элементы, которые находятся в "без пространства имен" и правильно ничего не выбирает, потому что любые элементы kmsg
в предоставленном XML-документе находятся в пространстве имен "http://url1"
, а не в "нет пространства имен".
Чтобы сделать это правильно:
oManager.AddNamespace("xxx", "http://url1");
Source.XPathSelectElement("//xxx:kmsg", oManager)
Ответ 2
Пространство имен URI, объявленное в исходном XML файле, не совпадает с идентификатором URI-пространства имен, которое вы регистрируете с помощью XmlNamespaceManager
.
В вашем исходном XML:
- В анонимном пространстве имен (без префикса) есть пространство имен-uri:
http://url1
- Префикс пространства env имеет пространство имен-uri:
url1
В XmlNamespaceManager
вы объявили:
- В анонимном пространстве имен (без префикса) есть пространство имен-uri:
http://xml.kerridge.net/k8msg
- Префикс пространства env имеет пространство имен-uri:
http://xml.kerridge.net/k8msgEnvelope
Значения namespace-uri должны совпадать, иначе вы выбираете разные имена элементов и никогда не получите соответствие.