Подтвердить что ты не робот

XDocument и Linq возвращают значение null, если элемент имеет атрибут xmlns

Новичок с XDocuments и Linq, предложите решение для извлечения данных из определенного тега в строке xml:

Если у меня есть XML-строка из ответа webservice (я отформатировал xml для удобства):

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <GetCashFlowReportResponse xmlns="http://tempuri.org/">
      <GetCashFlowReportPdf>Hello!</GetCashFlowReportPdf>
    </GetCashFlowReportResponse>
  </soap:Body>
</soap:Envelope>

Используя следующий код, я могу получить значение, только если тег GetCashFlowReportResponse не имеет атрибута "xmlns". Не знаете почему? В противном случае он всегда возвращает null.

string inputString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetCashFlowReportResponse xmlns=\"http://tempuri.org/\"><GetCashFlowReportPdf>Hello!</GetCashFlowReportPdf></GetCashFlowReportResponse></soap:Body></soap:Envelope>"    
XDocument xDoc = XDocument.Parse(inputString);
//XNamespace ns = "http://tempuri.org/";
XNamespace ns = XNamespace.Get("http://tempuri.org/");

var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
           select (string)c.Element("GetCashFlowReportPdf");

foreach (string val in data)
{
    Console.WriteLine(val);
}

Я не могу изменить веб-службу, чтобы удалить этот атрибут. Есть ли лучший способ прочитать ответ и вернуть фактические данные пользователю (в более читаемой форме)?

Отредактировано: РЕШЕНИЕ:

XDocument xDoc = XDocument.Parse(inputString);
XNamespace ns = "http://tempuri.org/";

var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
           select (string)c.Element(ns + "GetCashFlowReportPdf");
foreach (string val in data)
{
   Console.WriteLine(val);
}

Примечание. Даже если все дочерние элементы не имеют атрибута пространства имен, код будет работать, если вы добавите "ns" к элементу, так как я полагаю, что дочерние элементы наследуют пространство имен от родителя (см. ответ от SLaks).

4b9b3361

Ответ 1

Вам нужно включить пространство имен:

XNamespace ns = "http://tempuri.org/";

xDoc.Descendants(ns + "GetCashFlowReportResponse")

Ответ 2

XName qualifiedName = XName.Get("GetCashFlowReportResponse", 
    "http://tempuri.org/");

var data = from d in xDoc.Descendants(qualifiedName)

Ответ 3

Просто попросите элементы с использованием квалифицированных имен:

// create a XML namespace object
XNamespace ns = XNamespace.Get("http://tempuri.org/");

var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
           select (string)c.Element(ns + "GetCashFlowReportPdf");

Обратите внимание на использование перегруженного + оператора, который создает QName с пространством имен XML и локальной строкой имени.