Новичок с XDocuments и Linq, пожалуйста, предложите решение для извлечения данных из определенного тега в строке xml:
Если у меня есть XML-строка из ответа веб-службы (я отформатировал 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". Не уверен почему? Иначе, это всегда возвращает нуль.
GetCashFlowReportResponse
"xmlns"
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).
Вам необходимо включить пространство имен:
XNamespace ns = "http://tempuri.org/"; xDoc.Descendants(ns + "GetCashFlowReportResponse")
Просто запросите элементы, используя полные имена:
// 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 и локальной строкой имени.
XName qualifiedName = XName.Get("GetCashFlowReportResponse", "http://tempuri.org/"); var data = from d in xDoc.Descendants(qualifiedName)