简体   繁体   English

无法使用 XDocument 从 XML 中提取子元素

[英]Unable to extract child element from an XML using XDocument

Following is the XML from which I am trying to extract a child element.以下是我试图从中提取子元素的 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;
}

I want to extract the element Security Token.我想提取元素安全令牌。

Following are the things that I have already worked on:以下是我已经做过的事情:

  • Tried extracting the element using the approach suggested in the post How to get value of child node from XDocument尝试使用帖子中建议的方法提取元素如何从 XDocument 获取子节点的值

  • Also posting some code for reference.还发布了一些代码以供参考。 Both the statements that are assigning values to the Token variable are throwing "Object not set to an instance of an object"exception.将值分配给 Token 变量的两个语句都抛出“对象未设置为对象的实例”异常。

Thanks in advance.提前致谢。

You need to take into account the Header 's namepace.您需要考虑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;
}

Actually you could go ahead and just call实际上你可以提前 go 打电话

return XElement.Parse(response).Descendants()
            .First(x => x.Name.LocalName == "SecurityToken").Value;

For this response only, it makes sense to just parse the string and extract an element.仅对于此响应,仅解析字符串并提取元素是有意义的。 This response uses two namespaces, one for SOAP headers and another for the Amadeus login response.此响应使用两个命名空间,一个用于 SOAP 标头,另一个用于 Amadeus 登录响应。 You need the second one to retrieve the token:您需要第二个来检索令牌:

//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;

Other Amadeus responses are huge and XDocument won't be much better (if at all) than using WCF and deserializing to strongly typed objects.其他 Amadeus 响应很大,XDocument 不会比使用 WCF 和反序列化为强类型对象好多少(如果有的话)。 XDocument deserializes the entire XML response, the same as DataContractSerializer. XDocument 反序列化整个 XML 响应,与 DataContractSerializer 相同。 Instead of getting back a strongly-typed set of objects though, you get XElements you'll have to map to something else.但是,您无需返回一组强类型的对象,而是获得 XElements,您必须将 map 转换为其他对象。

If you want to reduce memory consumption by only reading the parts you'll have to use XmlReader and read the XML tokens from the response stream one by one.如果您想通过仅读取部分来减少 memory 消耗,您必须使用 XmlReader 并从响应 stream 中一一读取 XML 令牌。 That's a lot more work.这是更多的工作。

Another interesting thing is that Amadeus responses use multiple namespaces.另一个有趣的事情是 Amadeus 响应使用多个命名空间。 This response uses just 2. Other responses, eg searches, use many more.此响应仅使用 2 个。其他响应(例如搜索)使用更多。

You might consider working with System.Xml.XmlDocument and System.Xml.XPath.XPathNavigator which are really easy to work with.您可能会考虑使用System.Xml.XmlDocumentSystem.Xml.XPath.XPathNavigator ,它们非常易于使用。

I wrote a simple example for you (supporting UTF-8 encoding):我给你写了一个简单的例子(支持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
}

Please notice that you can also:请注意,您还可以:

  • Extract inner values using "@" key.使用“@”键提取内部值。

  • Move to the child using xmlNavigator.MoveToNext() .使用xmlNavigator.MoveToNext()移动到子级。

And many other things that you can read here .以及您可以在此处阅读的许多其他内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM