Разбор ответа SOAP с LINQ to XML - как получить вложенные узлы под родительским? - PullRequest
7 голосов
/ 07 февраля 2012

У меня есть SOAP-ответ, который выглядит примерно так:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <getLoginResponse xmlns="http://<remotesite>/webservices">
        <person_id>123456</person_id>
        <person_name>John Doe</person_name>
    </getLoginResponse>
  </soapenv:Body>
</soapenv:Envelope>

Мне удалось успешно извлечь узел <get LoginResponse ...> с помощью следующего кода LINQ:

string soapResult = rd.ReadToEnd();

XNamespace ns = "http://<remotesite>/webservices";

XDocument xDoc = XDocument.Parse(soapResult);

var respUser = (from r in xDoc.Descendants(ns + "getLoginResponse")
                select new User
                           {
                               Name = r.Element("person_name").Value
                           }).FirstOrDefault();

Однако , вызов Name = r.Element("person_name").Value дает мне ошибку Object reference not set to an instance of an object.

Я рассмотрел это далее, и я вижу, что если я выполню этот запрос, все значения (person_id, person_name) на самом деле находятся в вложенном .Descendants().Descendants() коллекции XElement:

var respUser = (from r in xDoc.Descendants(ns + "getLoginResponse") 
                select r).Descendants().ToList();

Итак, это говорит о том, что в моем исходном запросе LINQ я не извлекаю узлыв <getLoginResponse> правильно.

Как я могу объединить это вместе, используя ... select new User { ... } для заполнения моего пользовательского объекта?

Делая что-то вроде:

var respUser = (from r in xDoc.Descendants(ns + "getLoginResponse").Descendants()
                select new User()
                              {
                                 Name = r.Element("person_name").Value
                              }).FirstOrDefault();

Не делаетЭто работает очень хорошо:)

Спасибо всем за решение - я опустил пространство имен дочерних элементов, что вызвало мою проблему!

Ответы [ 2 ]

6 голосов
/ 07 февраля 2012

Вам необходимо добавить действительное пространство имен к вашему запросу, в вашем примере это будет "http://foobar/webservices", например ::

XElement xml = XElement.Load(@"testData.xml");
XNamespace foobar = "http://foobar/webservices";
string personId = xml.Descendants(foobar + "person_id").First().Value;
2 голосов
/ 07 февраля 2012

Вам необходимо включить пространство имен:

r.Element(ns + "person_name").Value
...