Невозможно извлечь дочерний элемент из XML с помощью XDocument - PullRequest
0 голосов
/ 05 ноября 2019

Ниже приведен XML-код, из которого я пытаюсь извлечь дочерний элемент.

<?xml version="1.0" encoding="UTF8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header xmlns="http://SomeValue/SomeValue/2009/01/SomeValue.xsd">
<Session>
<SessionId>SomeValue</SessionId>
<SequenceNumber>1</SequenceNumber>
<SecurityToken>SomeValue</SecurityToken>
</Session>
</soap:Header>
<soap:Body>
<Security_AuthenticateReply xmlns="http://SomeValue/SomeValue">
<processStatus>
<statusCode>P</statusCode>
</processStatus>
</Security_AuthenticateReply>
</soap:Body>
</soap:Envelope>
public static string AssignSecurityToken(string response)
{
        string Token = "";

        XNamespace ns = "http://schemas.xmlsoap.org/soap/envelope/";
        XElement xdoc = XElement.Parse(response);
        XElement root = xdoc.Descendants(ns + "Header").First();

        Token = root.Element("Session").Element("SecurityToken").Value;

        Token = root.Descendants("Session").Descendants().Where(n => n.Name == "SecurityToken").FirstOrDefault().Value;
        return Token;
}

Я хочу извлечь элемент Токен безопасности.

Ниже приведены вещи, которыеЯ уже работал над:

  • Попытка извлечения элемента с использованием подхода, предложенного в посте Как получить значение дочернего узла из XDocument

  • Также публикуем некоторый код для справки. Оба оператора, которые присваивают значения переменной Token, выдают исключение «Объект не установлен как экземпляр объекта».

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 05 ноября 2019

Вам необходимо принять во внимание пространство имен Header.

public static string AssignSecurityToken(string response)
{
    XNamespace ns1 = "http://schemas.xmlsoap.org/soap/envelope/";
    XNamespace ns2 = "http://SomeValue/SomeValue/2009/01/SomeValue.xsd";

    var envelope = XElement.Parse(response);
    var header = envelope.Element(ns1 + "Header");
    var session = header.Element(ns2 + "Session");
    var security_token = session.Element(ns2 + "SecurityToken");

    return security_token.Value;
}

На самом деле вы можете пойти дальше и просто позвонить

return XElement.Parse(response).Descendants()
            .First(x => x.Name.LocalName == "SecurityToken").Value;
1 голос
/ 05 ноября 2019

Только для этого ответа имеет смысл просто проанализировать строку и извлечь элемент. В этом ответе используются два пространства имен: одно для заголовков SOAP, а другое - для ответа на вход Amadeus. Вам нужен второй для получения токена:

//SOAP-only namespace
XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
//Default namespace
XNamespace ns = "http://SomeValue/SomeValue/2009/01/SomeValue.xsd";

var response=XElement.Parse(xml);
var token=response.Descendants(ns+"SecurityToken").First().Value;

Другие ответы Amadeus огромны, и XDocument не будет намного лучше (если вообще), чем использование WCF и десериализация для строго типизированных объектов. XDocument десериализует весь XML-ответ, так же, как DataContractSerializer. Вместо того чтобы возвращать строго типизированный набор объектов, вы получаете XElements, которые вам нужно сопоставить с чем-то другим.

Если вы хотите уменьшить потребление памяти, читая только те части, которые вам придется использоватьXmlReader и считывайте токены XML из потока ответов по одному. Это намного больше работы.

Еще одна интересная вещь заключается в том, что ответы Amadeus используют несколько пространств имен. Этот ответ использует только 2. Другие ответы, например поиски, используют еще много.

0 голосов
/ 05 ноября 2019

Вы можете рассмотреть возможность работы с System.Xml.XmlDocument и System.Xml.XPath.XPathNavigator, с которыми действительно легко работать.

Я написал для вас простой пример (с поддержкой кодировки UTF-8):

System.Xml.XmlDocument someXmlFile = new System.Xml.XmlDocument();
string xmlPath= @"YOUR_XML_FULL_PATH";
string innerNodeToExtract= @"/Session/SecurityToken";

try
{
    // Loading xml file with utf-8 encoding:
    string xmlFileStr= Systm.IO.File.ReadAllText(xmlPath, System.Text.Encoding.UTF8);

    // Creating the XPathNavigator:
    System.Xml.XPath.XPathNavigator xmlNavigator= someXmlFile.CreateNavigator();

    // Getting the inner value as string:
    string value = xmlNavigator.SelectSingleNode(innerNodeToExtract).Value;

    // some code...
}
catch(Exception) 
{
    // Handle failures
}

Обратите внимание, что вы также можете:

  • Извлечь внутренние значения с помощью клавиши "@".

  • Перейдите к ребенку, используя xmlNavigator.MoveToNext().

и многое другое, что вы можете прочитать здесь .

...