0
public string[] UnpackXML(string xml_string)
{
    string response = xml_string;
    string[] return_values = new string[6];

    XmlDocument xml = new XmlDocument();
    xml.LoadXml(response);

    return_values[0] = xml.GetElementsByTagName("meas name=\"mt1\"")[0].InnerText.ToString();
    return_values[1] = xml.GetElementsByTagName("meas name=\"mt2\"")[0].InnerText.ToString();
    return_values[2] = xml.GetElementsByTagName("meas name=\"mt3\"")[0].InnerText.ToString();
    return_values[3] = xml.GetElementsByTagName("meas name=\"mt4\"")[0].InnerText.ToString();
    return_values[4] = xml.GetElementsByTagName("meas name=\"mt5\"")[0].InnerText.ToString();
    return_values[5] = xml.GetElementsByTagName("meas name=\"mt6\"")[0].InnerText.ToString();

    return return_values;
}

When running the above code, it fails with the given error code:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

In the first line where I try to give return_values[0] a new value:

return_values[0] = xml.GetElementsByTagName("meas name=\"mt1\"")[0].InnerText.ToString();

The input to the UnpackXML is just an API response given as an XML string. The XML document has the following format:

<response location='location1'>
    <meas name='mt1'>14</meas>
    <meas name='mt2'>23</meas>
    <meas name='mt3'>65</meas>
    <meas name='mt4'>31</meas>
    <meas name='mt6'>32</meas>
</response>

Any ideas on how to fix this? I basically want to append specific fields from the XML file to an array. The XML attribute "name" exists with each line and has different values for the attribute. Is there a way to directly access the attribute values by giving the correct name = "nameValue", without looping through attributes and checking each specific value?

2 Answers 2

4

The .GetElementsByTagName() is not suitable for your scenario since you are querying with XPath but not only with tag name.

Instead, you should use .SelectNodes() or .SelectSingleNode().

return_values[0] = xml.SelectNodes("//meas[@name=\"mt1\"]")[0]?.InnerText.ToString();
return_values[1] = xml.SelectNodes("//meas[@name=\"mt2\"]")[0]?.InnerText.ToString();
return_values[2] = xml.SelectNodes("//meas[@name=\"mt3\"]")[0]?.InnerText.ToString();
return_values[3] = xml.SelectNodes("//meas[@name=\"mt4\"]")[0]?.InnerText.ToString();
return_values[4] = xml.SelectNodes("//meas[@name=\"mt5\"]")[0]?.InnerText.ToString();
return_values[5] = xml.SelectNodes("//meas[@name=\"mt6\"]")[0]?.InnerText.ToString();

Or

xml.SelectSingleNode("//meas[@name=\"mt1\"]")?.InnerText.ToString();

Demo @ .NET Fiddle

Also work with the null-conditional operator ?. to handle the returned node is possible null to prevent Null Reference Exception (NRE).


For your further question for dynamic way instead of hard code (assume 6 names you need to write the statements for 6 times), you may work with loop and LINQ to get the node's InnerText by matching the attribute value as below:

string[] return_values = new string[6];
string[] names = new string[6] { "mt1", "mt2", "mt3", "mt4", "mt5", "mt6" };
XmlDocument xml = new XmlDocument();
xml.LoadXml(response);
        
for (int i = 0; i < return_values.Count(); i++)
{
    var node = xml.DocumentElement
        .ChildNodes
        .Cast<XmlNode>()
        .FirstOrDefault(x => x.Attributes["name"].Value == names[i]);
    return_values[i] = node?.InnerText.ToString();
}

Or

for (int i = 0; i < return_values.Count(); i++)
{
    return_values[i] = xml.SelectSingleNode($"//meas[@name=\"{names[i]}\"]")?.InnerText.ToString();
}

Demo @ .NET Fiddle

Sign up to request clarification or add additional context in comments.

Comments

0

In case you have multiple entries for the response, it's recommended to load the return_values dynamically instead of writing every possible entry manually:

 public string[] UnpackXML(string xml_string)
 {
     XmlDocument xml = new XmlDocument();
     xml.LoadXml(xml_string);

     var response_childrens = xml.SelectSingleNode("response").ChildNodes;

     string[] return_values = new string[response_childrens.Count];

     for (int i = 0; i < response_childrens.Count; i++)
     {
        return_values[i] = response_childrens[i].InnerText;
     }

     return return_values;
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.