Reputation: 2528
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.
Upvotes: 2
Views: 1634
Reputation: 1823
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()")
});
Upvotes: 1
Reputation: 1232
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.
Upvotes: 0
Reputation: 6101
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
);
}
}
}
Upvotes: 0
Reputation: 94625
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;
//
}
Upvotes: 2
Reputation: 1296
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();
Upvotes: 0
Reputation: 5801
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.
Upvotes: 0