Нулевой возврат по XmlDocument.SelectSingleNode через правильный xpath

У меня в настоящее время есть следующий код

nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("soapenv", soapenv_namespace);
nsmgr.AddNamespace("de", de_namespace);

XmlNode xnEnvelope = xmlDoc.SelectSingleNode("//soapenv:Envelope", nsmgr);
XmlNode xnBody = xmlDoc.SelectSingleNode("//soapenv:Envelope/soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("//soapenv:Envelope/soapenv:Body/message", nsmgr);

Который анализирует следующий xml (усеченный для удобства чтения)

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
     <soapenv:Body>
        <message     xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse"     xmlns:ns2="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractReferenceResponse" xmlns:ns3="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractRequest" xmlns:ns4="http://www.origostandards.com/schema/tech/v1.0/SOAPFaultDetail">
        <de:m_content .....

Проблема в строке XmlNode xnMessage = xnBody.SelectSingleNode("//soapenv:Envelope/soapenv:Body/message", nsmgr); возвращает ноль, когда я ожидал, что он вернет элемент сообщения.

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

Любые указатели будут оценены.

2 ответа

Решение

Вы ввели здесь пространство имен по умолчанию:

xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse" 

что приводит к message элемент и все его потомки без префикса распознаются как в этом пространстве имен по умолчанию (если только у потомка нет локального пространства имен по умолчанию). Чтобы получить доступ к элементу в пространстве имен по умолчанию, просто зарегистрируйте префикс, например dи сопоставьте его с пространством имен по умолчанию uri:

nsmgr.AddNamespace("d", "http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse");

Затем используйте заново зарегистрированный префикс соответственно в выражении XPath:

XmlNode xnBody = xmlDoc.SelectSingleNode("//soapenv:Envelope/soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("d:message", nsmgr);

Это работает

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"C:\Users\DummyUser\Desktop\Noname1.xml");

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("de", "http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse");

XmlNode xnEnvelope = xmlDoc.SelectSingleNode("//soapenv:Envelope", nsmgr);
XmlNode xnBody = xnEnvelope.SelectSingleNode("//soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("de:message", nsmgr);

и XML-файл

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
 <soapenv:Body>
    <message xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse"     xmlns:ns2="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractReferenceResponse" 
    xmlns:ns3="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractRequest" 
    xmlns:ns4="http://www.origostandards.com/schema/tech/v1.0/SOAPFaultDetail">
    This is my sample message
    </message>
</soapenv:Body>
</soapenv:Envelope>
Другие вопросы по тегам