0

I'm downloading some CSV data as part of an API response and the last column of the CSV data contains an XML snippet as below:

<tns:Event xmlns:tns="http://someurl">
 <tns:MaximumSeverity.Code>Error</tns:MaximumSeverity.Code>
  <tns:EventItems>
   <tns:EventItem>
   <tns:Error.Code>ERRORCODE</tns:Error.Code>
   <tns:Severity.Code>Error</tns:Severity.Code>
   <tns:Short.Description>Short error</tns:Short.Description>
   <tns:Detailed.Description>Longer error</tns:Detailed.Description>
   <tns:Parameters></tns:Parameters>
  </tns:EventItem>
 </tns:EventItems>
</tns:Event>

I'd like to extract the text from either the short or detailed description so I'm wondering what the most efficient way is of doing this?

There could be multiple EventItem elements within the XML.

I tried the code below but got an XPathException:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
XmlNodeList nodeList = doc.SelectNodes("/tns:Event");
foreach (XmlNode node in nodeList)
{
    string errorTxt = node.SelectSingleNode("Short.Description").InnerText;
    Console.WriteLine(errorTxt);
}
Console.ReadKey();
kennyzx
  • 12,845
  • 6
  • 39
  • 83
bn25
  • 47
  • 7
  • Use `XDocument` class which is much easier than `XmlDocument`, and you need to deal with xml namespace. you may find [this](https://stackoverflow.com/questions/2998710/xdocument-containing-namespaces) helpful – kennyzx Sep 12 '18 at 05:36
  • Thank you for that. I'll take a look and let you know how I go. – bn25 Sep 12 '18 at 05:47

2 Answers2

0

Use XDocument class which is much easier than XmlDocument, and you need to deal with xml namespace.

Something like this

using System.Xml.Linq;

XDocument xDoc = XDocument.Parse(xml); //xml is the string you pasted
XNamespace tns = "http://someurl";
var eventItems = xDoc.Element(tns + "Event").Element(tns + "EventItems").Elements(tns + "EventItem");
foreach (var eventItem in eventItems)
{
    Console.WriteLine(eventItem.Element(tns + "Short.Description").Value);
    Console.WriteLine(eventItem.Element(tns + "Detailed.Description").Value);
}
kennyzx
  • 12,845
  • 6
  • 39
  • 83
  • I get a NullReferenceException when trying the code above. Could it be that it doesn't recognize "Event" with the "tns:" prefix? – bn25 Sep 12 '18 at 06:15
  • 1
    For XML to understand meaning of tns namespace - xmlns:tns="http://someurl" is used in the root. In the above code namespace is set accordingly using XNamespace tns = "http://someurl"; So it should work. Code by @kennyzx is working – ManishM Sep 12 '18 at 07:09
  • My apologies. The code works perfectly after I edited the correct namespace in the string. Thank you this gives me a great starting point for what I need to do. – bn25 Sep 12 '18 at 09:34
0

I tried the code by @kennyzx and its working

    string xml = @"<tns:Event xmlns:tns=""http://someurl""><tns:MaximumSeverity.Code>Error</tns:MaximumSeverity.Code><tns:EventItems><tns:EventItem><tns:Error.Code>ERRORCODE</tns:Error.Code>
   <tns:Severity.Code>Error</tns:Severity.Code>
   <tns:Short.Description>Short error1</tns:Short.Description>
   <tns:Detailed.Description>Longer error2</tns:Detailed.Description>
   <tns:Parameters></tns:Parameters>
  </tns:EventItem>
  <tns:EventItem><tns:Error.Code>ERRORCODE</tns:Error.Code>
   <tns:Severity.Code>Error</tns:Severity.Code>
   <tns:Short.Description>Short error2</tns:Short.Description>
   <tns:Detailed.Description>Longer error2</tns:Detailed.Description>
   <tns:Parameters></tns:Parameters>
  </tns:EventItem>
 </tns:EventItems>
</tns:Event>";

XDocument xDoc = XDocument.Parse(xml);
XNamespace tns = "http://someurl";
var eventItems = xDoc.Element(tns + "Event").Element(tns + "EventItems").Elements(tns + "EventItem");
foreach (var eventItem in eventItems)
{
    Console.WriteLine(eventItem.Element(tns + "Short.Description").Value);
    Console.WriteLine(eventItem.Element(tns + "Detailed.Description").Value);
}

enter image description here

ManishM
  • 583
  • 5
  • 7