2

Morning,

I am have some XML which is being returned, and i need to read each of the result nodes, and then put them into my DB.

So SKU, ResultMessageCode would be stored. I need to only pull these out if ResultCode is marked as an error.

 <Message>
    <MessageID>1</MessageID>
    <ProcessingReport>
        <DocumentTransactionID>123456789</DocumentTransactionID>
        <StatusCode>Complete</StatusCode>
        <ProcessingSummary>
            <MessagesProcessed>2</MessagesProcessed>
            <MessagesSuccessful>0</MessagesSuccessful>
            <MessagesWithError>2</MessagesWithError>
            <MessagesWithWarning>0</MessagesWithWarning>
        </ProcessingSummary>
        <Result>
            <MessageID>1</MessageID>
            <ResultCode>Error</ResultCode>
            <ResultMessageCode>90205</ResultMessageCode>
            <ResultDescription>Some Text Here</ResultDescription>
            <AdditionalInfo>
                <SKU>12345</SKU>
            </AdditionalInfo>
        </Result>
        <Result>
            <MessageID>2</MessageID>
            <ResultCode>Error</ResultCode>
            <ResultMessageCode>90205</ResultMessageCode>
            <ResultDescription>Some Text Here</ResultDescription>
            <AdditionalInfo>
                <SKU>67890</SKU>
            </AdditionalInfo>
        </Result>
    </ProcessingReport>
</Message>

I found this elsewhere on Stackoverflow, and think this maybe what i am after.

 foreach (XmlNode chldNode in node.ChildNodes)
    {
            **//Read the attribute Name**
        if (chldNode.Name == Employee)
        {                    
            if (chldNode.HasChildNodes)
            {
                foreach (XmlNode item in node.ChildNodes)
                { 

                }
            }
        }
    }

Am i assuming correctly here, and would need to use something similar? however the XML from the above sample was slightly smaller.

Thanks in advance.

thatuxguy
  • 2,418
  • 7
  • 30
  • 51
  • http://stackoverflow.com/questions/1600065/how-to-read-attribute-value-from-xmlnode-in-c - article for mentioned sample code. – thatuxguy Jul 10 '12 at 08:46

6 Answers6

2

Try LINQ-XML,

XDocument doc = XDocument.Parse(xmlStr);

var results = doc.Root.Descendants("Result")
                    .Where(p => p.Element("ResultCode").Value == "Error");
foreach (var t in results)
 {
  var resultCode = t.Element("ResultMessageCode").Value;
  var sku = t.Element("AdditionalInfo").Element("SKU").Value;
  //
 }
KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • He's just going to copy paste this. Using fancy LINQ to XML isn't going to help him understand what's going, or why it's being done a certain way. Well done. – Zoran Pavlovic Jul 10 '12 at 11:31
1

Still another (concise) way to do this is to use XPath and Linq:

var dom = new XmlDocument();
dom.LoadXml(xml);
var results = dom.SelectNodes("//Message/ProcessingReport/Result[ResultCode/text() = 'Error']")
                .Cast<XmlNode>()
                .Select(n => new { 
                    ResultMessageCode = n.SelectSingleNode("ResultMessageCode/text()"), 
                    SKU = n.SelectSingleNode("AdditionalInfo/SKU/text()")
                });
an phu
  • 1,823
  • 1
  • 16
  • 10
0

Yes you need to use something silimiar or use LINQ to XML which gives you more clean and compact code:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    private const string Xml =
        @"<Message>
    <MessageID>1</MessageID>
    <ProcessingReport>
        <DocumentTransactionID>123456789</DocumentTransactionID>
        <StatusCode>Complete</StatusCode>
        <ProcessingSummary>
            <MessagesProcessed>2</MessagesProcessed>
            <MessagesSuccessful>0</MessagesSuccessful>
            <MessagesWithError>2</MessagesWithError>
            <MessagesWithWarning>0</MessagesWithWarning>
        </ProcessingSummary>
        <Result>
            <MessageID>1</MessageID>
            <ResultCode>Error</ResultCode>
            <ResultMessageCode>90205</ResultMessageCode>
            <ResultDescription>Some Text Here</ResultDescription>
            <AdditionalInfo>
                <SKU>12345</SKU>
            </AdditionalInfo>
        </Result>
        <Result>
            <MessageID>2</MessageID>
            <ResultCode>Error</ResultCode>
            <ResultMessageCode>90205</ResultMessageCode>
            <ResultDescription>Some Text Here</ResultDescription>
            <AdditionalInfo>
                <SKU>67890</SKU>
            </AdditionalInfo>
        </Result>
    </ProcessingReport>
</Message>
";

    static void Main(string[] args)
    {
        var doc = XDocument.Parse(Xml);

        foreach (var result in doc.Descendants("Result").Where(x => x.Element("ResultCode").Value == "Error"))
        {
            Console.WriteLine("MessageID: {0}; ResultMessageCode: {1}; ResultDescription: {2}", 
                result.Element("MessageID").Value,
                result.Element("ResultMessageCode").Value,
                result.Element("ResultDescription").Value
                );
        }
    }
}
ie.
  • 5,982
  • 1
  • 29
  • 44
0
using (XmlReader xmlr = XmlReader.Create(@"http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"))
        {
            xmlr.ReadToFollowing("Cube");
            while (xmlr.Read())
            {
                if (xmlr.NodeType != XmlNodeType.Element) continue;

this way you can navigate to the nodes that you only need. This is just a way to do it. Linq to XML is another way but is more resource intensive than the snippet above.

Freeman
  • 5,691
  • 3
  • 29
  • 41
  • the xml i have is in a string I am already pulling some info out of it using `doc.SelectSingleNode("/Message/ProcessingReport/StatusCode").InnerText.ToUpper().ToString()` With this work in the same way? – thatuxguy Jul 10 '12 at 08:55
  • of course, you can try it, it just jumps to the nodes of your interest. – Freeman Jul 10 '12 at 09:04
0

You could make a set of classes for your XML structure, and add serializable keys to the classes,

[Serializable()]
public class Message
{
    public int MessageId {get; set;}

    private ProcessingReport processingReport = new ProcessingReport();
    ...
}

And then use the XmlSerializer to parse your XML into the class

    XmlSerializer SerializerObj = new XmlSerializer(typeof(Message));

    // Open your XML file (or use a reader if it's a a location)
    FileStream ReadFileStream = new FileStream(@"C:\test.xml", FileMode.Open, FileAccess.Read, FileShare.Read);

    Message message = (Message)SerializerObj.Deserialize(ReadFileStream);

    ReadFileStream.Close();
John
  • 1,268
  • 16
  • 25
0

You can use xpath to find the "ResultCode" node, and then determine if it is in error.

http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectnodes%28v=vs.71%29.aspx http://support.microsoft.com/kb/307548

using System.Xml;

XmlDocument doc = new XmlDocument();
doc.LoadXml(XML_String);

XmlNode result = doc.DocumentElement.SelectSingleNode("//ResultCode");

if (result == null)
    throw new Exception("Error")

if (result.Value == "Error")
    //Message is in Error.
else
    //Message is OK.
Zoran Pavlovic
  • 1,166
  • 2
  • 23
  • 38