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?
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();
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();
}