简体   繁体   中英

Parsing URL/web-service

I made a request to a third party API and it gives me the following response in XML.

<?xml version="1.0" ?>
<abc>
<xyz>
<code>-112</code>
<message>No such device</message>
</xyz>
</abc>

I read this using this code.

 XmlDocument doc = new XmlDocument();
    doc.Load("*** url ***");

    XmlNode node = doc.SelectSingleNode("/abc/xyz");
    string code = node.SelectSingleNode("code").InnerText;
    string msg = node.SelectSingleNode("message").InnerText;

    Response.Write("Code: " + code);
Response.Write("Message: "+ msg);

But I get an error on this line:

string code = node.SelectSingleNode("code").InnerText;

Error is:

Object reference not set to an instance of an object.

I changed the first line of your XML file into:

<?xml version="1.0"?>

to make it valid XML. With this change, your code works for me. Without the change, the parser throws an exception.

As you've given it, there doesn't seem to be anything wrong with your code Edit : Your declaration is wrong, as svinja pointed out, and your xml won't even load into the XmlDocument.

However, I'm guessing that your xml is more complicated, and there is at least one namespace involved, which would cause the select to fail.

It isn't pretty, but what you can do is use namespace agnostic xpath to locate your nodes to avoid using a XmlNamespaceManager :

XmlDocument doc = new XmlDocument();
doc.Load("*** url ***");

XmlNode node = doc.SelectSingleNode("/*[local-name()='abc']/*[local-name()='xyz']");
string code = node.SelectSingleNode("*[local-name()='code']").InnerText;
string msg = node.SelectSingleNode("*[local-name()='message']").InnerText;

Response.Write("Code: " + code);
Response.Write("Message: "+ msg);

Edit - Elaboration

Your code works fine if you correct the declaration to <?xml version="1.0"?>

However, if you introduce namespaces into the mix, your code will fail unless you use namespace managers appropriately.

My agnostic xpath above will also parse an xml document like so:

<?xml version="1.0"?>
<abc xmlns="foo">
    <xyz xmlns="bar">
        <code xmlns="bas">-112</code>
        <message xmlns="xyz">No such device</message>
    </xyz>
</abc>

You can use LINQ to XML (if confortable):

  XDocument doc = XDocument.Load(url);
  var selectors = (from elements in  doc.Elements("abc").Elements("xyz")
                  select elements).FirstOrDefault();
  string code = selectors.Element("code").Value;
  string msg = selectors.Element("message").Value;
[XmlRoot("abc")]
public class Entity
{
    [XmlElement("xyz")]
    public SubEntity SubEntity { get; set; }
}

public class SubEntity
{
    [XmlElement("code")]
    public string Code { get; set; }
    [XmlElement("message")]
    public string Message { get; set; }
}

And use standart xmlserializer

       var xmlSerializer = new XmlSerializer(typeof(Entity));
       var result = xmlSerializer.Deserialize(new XmlTextReader("*** url ***"));
       Response.Write("Code: " + result.SubEntity.Code);
       Response.Write("Message: "+ result.SubEntity.Message);
<?xml version="1.0">
<abc>
  <xyz>
    <code>-112</code>
    <message> No such device </message>
  </xyz>
</abc>

try to set a list:

XmlNodeList nodeList = root.SelectNodes("/abc/xyz");

then read all the nodes and get their text:

foreach(XmlNode node in nodeList)
{
  if(node.Name == "code")
  {
    string code = node.InnerText;
  }
  else
  if(node.Name == "message")
  {
    string msg = node.InnerText;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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