Reading XML and creating a frequency count of elements in C# - c#

I have an XML file in this format (but only much bigger) :
<customer>
<name>John</name>
<age>24</age>
<gender>M</gender>
</customer>
<customer>
<name>Keith</name>
<age></age> <!--blank value-->
<gender>M</gender>
</customer>
<customer>
<name>Jenny</name>
<age>21</age>
<gender>F</gender>
</customer>
<customer>
<name>John</name>
<age>24</age> <!--blank value-->
<gender>M</gender> <!--blank value-->
</customer>
I want to generate a DataTable which will be in this format :
Element Name   Value   Frequency name       filled     4name       blank    0age        filled     2age       blank    2gender      filled    3gender      blank    1
Currently I am completing this task in 2 parts, first creating a DataTable structure as above and setting all the frequencies to 0 as default. And then reading the XML using XmlReader, and increasing the count of the frequency everytime XmlReader finds a child element.
My problem is that the second function that I use for adding the actual count is taking too long for very big Xml files with many customers having many attributes. How can I improve the efficiency of this function? My code :
static void AddCount(DataTable dt)
{
int count;
using (XmlReader reader = XmlReader.Create(#"C:\Usr\sample.xml"))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
string eleName = reader.Name;
DataRow[] foundElements = dt.Select("ElementName = '" + eleName + "'");
if (!reader.IsEmptyElement)
{
count = int.Parse(foundElements.ElementAt(0)["Frequency"].ToString());
foundElements.ElementAt(0).SetField("Frequency", count + 1);
}
else
{
count = int.Parse(foundElements.ElementAt(0)["Frequency"].ToString());
foundElements.ElementAt(0).SetField("Frequency", count + 1);
}
}
}
}
}
I am also ready to change the XmlReader class for any other more efficient class for this task. Any advice is welcome.

It turned out that querying in the DataTable using the Select operation was very expensive and that was making my function very slow.
Instead of that, used a Dictionary<string, ValueFrequencyModel> and queried on that to fill the dictionary with the count, and after completing that, converted the Dictionary<string, ValueFrequencyModel> into a DataTable.
This saved loads of time for me and solved the problem.

You can use following code:
using (XDocument xdoc = XDocument.Load(#"C:\Users\aks\Desktop\sample.xml"))
{
var customers = xdoc.Descendants("customer");
var totalNodes = customers.Count();
var filledNames = customers.Descendants("name").Where(x => x.Value != string.Empty).Count();
var filledAges = customers.Descendants("age").Where(x => x.Value != string.Empty).Count();
var filledGenders = customers.Descendants("gender").Where(x => x.Value != string.Empty).Count();
var unfilledNames = totalNodes - filledNames;
var unfilledAges = totalNodes - filledAges;
var unfilledGenders = totalNodes - filledGenders;
}

Try this logic, currently I have only taken only one attribute here ie Name
XDocument xl = XDocument.Load(#"C:\Usr\sample.xml");
var customers = xl.Descendants("Customer");
var customerCount = customers.Count();
var filledCustomers = customers.Where(x => x.Element("Name").Value != string.Empty).Count();
var nonfilledCustomers = customerCount - filledCustomers;

Related

Create XML file with custom formatting

I need to create an XML file with line breaks and tabs in Attributes and on few tags as well. So I tried like below.
string xmlID = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<PersonLib Version=\"1.0\"></PersonLib>";
XDocument doc = XDocument.Parse(xmlID);//, LoadOptions.PreserveWhitespace);
XElement device = doc.Root;
using (StringWriter str = new StringWriter())
using (XmlTextWriter xml = new XmlTextWriter(str))
{
xml.Formatting=Formatting.Indented;
xml.WriteStartElement("Details");
xml.WriteWhitespace("\n\t");
xml.WriteStartElement("Name");
xml.WriteWhitespace("\n\t\t");
xml.WriteStartElement("JohnDoe");
xml.WriteAttributeString("DOB", "10");
xml.WriteAttributeString("FirstName", "20");
xml.WriteAttributeString("LastName", "40");
xml.WriteAttributeString("\n\t\t\tAddress", "50");
xml.WriteAttributeString("\n\t\t\tPhoneNum", "60");
xml.WriteAttributeString("\n\t\t\tCity", "70");
xml.WriteAttributeString("\n\t\t\tState", "80");
xml.WriteAttributeString("\n\t\t\tCountry", "90");
//xml.WriteWhitespace("\n\t\t");
xml.WriteEndElement();
xml.WriteWhitespace("\n\t");
xml.WriteEndElement();
xml.WriteWhitespace("\n");
xml.WriteEndElement();
Console.WriteLine(str);
device.Add(XElement.Parse(str.ToString(), LoadOptions.PreserveWhitespace));
File.WriteAllText("MyXML.xml", device.ToString());
I can get the XML generated in format I need but the issue comes when I try to add it to the parent XMLElement device in this case. The formatting is all gone despite LoadOptions.PreserveWhitespace.
I get
<PersonLib Version="1.0">
<Details>
<Name>
<JohnDoe DOB="10" FirstName="20" LastName="40" Address="50" PhoneNum="60" City="70" State="80" Country"90" />
</Name>
</Details>
</PersonLib >
while I need
<PersonLib Version="1.0">
<Details>
<Name>
<JohnDoe DOB="10" FirstName="20" LastName="40"
Address="50"
PhoneNum="60"
City="70"
State="80"
Country="90" />
</Name>
</Details>
</PersonLib >
Not sure what am I missing.
You should take a look at this question: xdocument save preserve white space inside tags
LoadOptions.PreserveWhitespace (LoadOptions Enum)
If you preserve white space when loading, all insignificant white
space in the XML tree is materialized in the XML tree as is. If you do
not preserve white space, then all insignificant white space is
discarded.
This gives the impression that 'insignificant' whitespace between attributes would be preserved.
If however you look at XElement.Parse Method you see this:
If the source XML is indented, setting the PreserveWhitespace flag in
options causes the reader to read all white space in the source XML.
Nodes of type XText are created for both significant and insignificant
white space.
Looking at the class hierarchy you can see that XAttribute does not inherit from XNode. The long and the short of that is whitespace between attributes are not preserved. If they were you would still have to disable formatting on output (something like ToString(SaveOptions.DisableFormatting)).
I don't think that attributes were designed to be used as you have, but it is a very common usage. There is considerable diversity of opinion about this (see: Attribute vs Element)
Either way it sounds like you are stuck with both the design and format of what you were given. Unfortunately, this means you are also stuck with having to create a custom formatter to get the output you need.
Note the following code is meant only as an example of one possible way to implement code that creates the format you ask about.
using System;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace FormatXml {
class Program {
static String OutputElement(int indentCnt, XElement ele) {
StringBuilder sb = new StringBuilder();
var indent = "".PadLeft(indentCnt, '\t');
var specialFormat = (ele.Parent == null) ? false : ((ele.Parent.Name == "Name") ? true : false);
sb.Append($"{indent}<{ele.Name}");
String FormatAttr(XAttribute attr) {
return $"{attr.Name} = '{attr.Value}'";
}
String FormatAttrByName(String name) {
var attr = ele.Attributes().Where(x => x.Name == name).FirstOrDefault();
var rv = "";
if (attr == null) {
rv = $"{name}=''";
}
else {
rv = FormatAttr(attr);
}
return rv;
}
if (specialFormat) {
var dob = FormatAttrByName("DOB");
var firstName = FormatAttrByName("FirstName");
var lastName = FormatAttrByName("LastName");
var address = FormatAttrByName("Address");
var phoneNum = FormatAttrByName("PhoneNum");
var city = FormatAttrByName("City");
var state = FormatAttrByName("State");
var country = FormatAttrByName("Country");
sb.AppendLine($"{dob} {firstName} {lastName}");
var left = ele.Name.LocalName.Length + 5;
var fill = indent + "".PadLeft(left);
sb.AppendLine($"{fill}{address}");
sb.AppendLine($"{fill}{phoneNum}");
sb.AppendLine($"{fill}{city}");
sb.AppendLine($"{fill}{state}");
sb.AppendLine($"{fill}{country} />");
}
else {
foreach (var attr in ele.Attributes()) {
sb.AppendFormat(" {0}", FormatAttr(attr));
}
}
sb.AppendLine(">");
foreach (var e in ele.Elements()) {
sb.Append(OutputElement(indentCnt + 1, e));
}
sb.AppendLine($"{indent}</{ele.Name}>");
return sb.ToString();
}
static void Main(string[] args) {
var txtEle = #"
<Details>
<Name>
<JohnDoe DOB = '10' FirstName = '20' LastName = '40'
Address = '50'
PhoneNum = '60'
City = '70'
State = '80'
Country = '90' />
</Name>
</Details>";
var plib = new XElement("PersonLib");
XDocument xdoc = new XDocument(plib);
var nameEle = XElement.Parse(txtEle, LoadOptions.PreserveWhitespace);
xdoc.Root.Add(nameEle);
var xml = OutputElement(0, (XElement)xdoc.Root);
Console.WriteLine(xml);
}
}
}

Xml file with C# can't get the value

Here is my xml file
<?xml version="1.0" encoding="ASCII"?>
<Vitals>
<Vendor>General Electric Healthcare</Vendor>
<Model>Pro/Procare</Model>
<Result name="Mean_arterial_pressure">
<Value>86</Value>
<Units name="mmHg"></Units>
<Time_stamp year="2008" month="11" day="18" hour="12" minute="33" second="14"></Time_stamp>
</Result>
<Result name="Systolic_blood_pressure">
<Value>130</Value>
<Units name="mmHg"></Units>
<Time_stamp year="2008" month="11" day="18" hour="12" minute="33" second="14"></Time_stamp>
</Result>
<Result name="Diastolic_blood_pressure">
<Value>67</Value>
<Units name="mmHg"></Units>
<Time_stamp year="2008" month="11" day="18" hour="12" minute="33" second="14"></Time_stamp>
</Result>
<Result name="Pulse">
<Value>73</Value>
<Units name="BPM"></Units>
<Method>blood_pressure</Method>
<Time_stamp year="2008" month="11" day="18" hour="12" minute="33" second="14"></Time_stamp>
</Result>
</Vitals>
and Here is my sourcecode, I having the issue how to get the result name and the value?
private void btnReadXml_Click(object sender, EventArgs e)
{
Hashtable h = new Hashtable();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("C:\\dinamap.xml");
XmlNodeList doc_results = xmlDoc.GetElementsByTagName("Vitals/Vendor/Model/Result[#name='Systolic_blood_pressure']");
foreach (XmlNode pnode in doc_results)
{
foreach (XmlNode cnode in pnode.ChildNodes)
{
if (cnode.Name == "Value")
{
h.Add(pnode.Attributes["name"].InnerText + cnode.Name, cnode.Attributes["name"].InnerText);
}
else
{
h.Add(pnode.Attributes["name"].InnerText + "_" + cnode.Name, cnode.InnerText);
}
}
}
}
May I know what wrong of my code? always can't get the value.
I need to get the value from xml file.
On line 5, your xPath specify Model is a child of Vendor while Vendor contains only a string (<Vendor>General Electric Healthcare</Vendor>).
Moreover, to navigate with xPath i advice you to use SelectNodes function.
Try this instead :
XmlNodeList doc_results = xmlDoc.SelectNodes("/Vitals/Model/Result[#name='Systolic_blood_pressure']");
It'd be easier if you used LINQ to XML for this.
var doc = XDocument.Load("path/to/xml");
var results =
from result in doc.Descendants("Result")
select new
{
Name = (string) result.Attribute("name"),
Value = (string) result.Element("Value"),
Units = (string) result.Element("Units").Attribute("name")
};
You could then filter by Name if you needed:
var sysBp = results.Single(x => x.Name == "Systolic_blood_pressure");
See this fiddle for a working demo.
You're currently trying to retrieve the "name" attribute of the child node, which it does not actually have in the case of your value node. If you use cnode.Value you can get the contents of a text note.
Also, Result is not a child of Model, which is not a child of Vendor. You'll either want to properly make them children or change the path you're setting for doc_results
private void btnReadXml_Click(object sender, EventArgs e)
{
var doc = XDocument.Load("C:\\dinamap.xml");
var results = from result in doc.Descendants("Result")
select new
{
Name = (string)result.Attribute("name"),
Value = (string)result.Element("Value"),
Units = (string)result.Element("Units").Attribute("name")
};
foreach (var result in results)
{
MessageBox.Show("{result.Name}: {result.Value} {result.Units}");
}
}

XElement.Elements() returning empty collection

I'm trying to get the values from an XElement that I'm receiving from db notification.
The xml structure is like this:
<?xml version="1.0"?>
<root>
<inserted>
<row>
<CODI_AVERIA>22</CODI_AVERIA>
<NUMERO_LINIA>2</NUMERO_LINIA>
<DIA>2016-07-17T00:00:00</DIA>
<HORA>1899-12-30T10:26:15.790</HORA>
<CODI_USUARI>1</CODI_USUARI>
<ACCIO>0</ACCIO>
<CODI_PSEUDO>-1</CODI_PSEUDO>
</row>
</inserted>
</root>
And this is the method that I'm using to get the data, and it returns me a List that is empty.
static void getAccio(XElement xml)
{
try
{
xml.Descendants("deleted").Remove();
var items = xml.Elements("row").Select(n => new
{
Codi_averia = n.Element("CODI_AVERIA").Value,
Numero_linia = n.Element("NUMERO_LINIA)").Value,
Accio = n.Element("ACCIO").Value
}).ToList();
}
catch (Exception e)
{
Console.Write(e.Message);
}
}
I have tried to get the value of each field apart and it doesn't allow me to get them separetly as XElements.
Use .Descendants() instead of .Elements():
var items = xml.Descendants("row").Select(n => new
{
Codi_averia = n.Element("CODI_AVERIA").Value,
Numero_linia = n.Element("NUMERO_LINIA)").Value,
Accio = n.Element("ACCIO").Value
}).ToList();
.Elements finds only those elements that are direct descendents, i.e. immediate children. - And I assume that your XElement is the parent of the inserted section.
For difference between .Element and .Descendants see this question
If you don't want to find them in all inner elements too then do .Element("inserted").Elements("rows")
Your document doesn't have any root element with the name row. Instead, you need to select inserted first, and enumerate the row elements of inserted:
var xml = #"<inserted>
<row>
<CODI_AVERIA>21</CODI_AVERIA>
<NUMERO_LINIA>2</NUMERO_LINIA>
<DIA>2016-07-17T00:00:00</DIA>
<HORA>1899-12-30T10:26:15.790</HORA>
<CODI_USUARI>1</CODI_USUARI>
<ACCIO>0</ACCIO>
<CODI_PSEUDO>-1</CODI_PSEUDO>
</row>
</inserted>";
var xdoc = XDocument.Parse(xml);
var items = xdoc.Element("inserted").Elements("row").Select(n => new
{
Codi_averia = n.Element("CODI_AVERIA").Value,
Numero_linia = n.Element("NUMERO_LINIA").Value,
Accio = n.Element("ACCIO").Value
}).ToList();
In your sample code ("NUMERO_LINIA)") is wrong because of additionnal quote and parenthesis.
This works for me :
XDocument xd = XDocument.Load("XMLFile1.xml");
var lst = (from n in xd.Descendants("row")
select new
{
Codi_averia = n.Element("CODI_AVERIA").Value,
Numero_linia = n.Element("NUMERO_LINIA").Value,
Accio = n.Element("ACCIO").Value
}).ToList();
foreach (var item in lst)
Console.WriteLine(string.Format("{0}{1}{2}", item.Codi_averia, item.Numero_linia, item.Accio));

Why is this program not accessing child nodes?

Here it gets the XML document and individual nodes, and inserts the nodes into a dictionary.
//create the xml document obj
XmlDocument inputXMLDoc = new XmlDocument();
fileref.isValid = false;
//load the xml document
#region
try
{
inputXMLDoc.XmlResolver = null;
inputXMLDoc.Load( strfile );//load the xml file
string input = inputXMLDoc.OuterXml;//get the string
Console.WriteLine( "success,loaded XML" );
logger.Log( "loaded xml:" + strfile );
fileref.importList = new Dictionary<string, XmlNode>();
nodeNames = new List<string> { "OrderId", "CustomerId", "CustomerName", "Addresses", "OrderStatus", "DateOrdered", "PaymentTime", "IncludeVAT", "OrderTotalIncVat", "OrderTotalVat", "Currency", "TypeOfSaleId" };
try
{
int i = 0;
foreach( string name in nodeNames )
{
Console.WriteLine( "Adding xml node " + name );
if( inputXMLDoc.GetElementsByTagName( name ) != null )
{
XmlNodeList xlist = inputXMLDoc.GetElementsByTagName( name );
foreach( XmlNode node in xlist )
{
fileref.importList.Add( name, node );
//add individual node within nodelist
Console.WriteLine( name );
}
} //add specified node from XML doc
else
{
nodeNames.RemoveAt( i );
}
i++;
}
}
}
Later, the nodes are accessed to save the information to a web service. However, nodes with child nodes within are not showing up this way.
Invoices.Address address = new Invoices.Address();
XmlNodeList oNodeList = fileref.importList["Addresses"].SelectNodes("/Delivery/Street");
foreach (XmlNode xn in oNodeList)
{
address.Street = xn.InnerText;
}
Sample XML document
<?xml version="1.0" encoding="utf-8"?>
<InvoiceOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OrderId xmlns="http://24sevenOffice.com/webservices">35</OrderId>
<CustomerId xmlns="http://24sevenOffice.com/webservices">21</CustomerId>
<CustomerName xmlns="http://24sevenOffice.com/webservices">James Bond</CustomerName>
<Addresses xmlns="http://24sevenOffice.com/webservices">
<Delivery>
<Street>11 Shewell Walk</Street>
<State />
<PostalCode>CO1 1WG</PostalCode>
<PostalArea>Essex</PostalArea>
<Name />
<City>Colchester</City>
<Country>UK</Country>
</Delivery>
<Invoice>
<Street>10 Shewell Walk</Street>
<State />
<PostalCode>CO1 1WG</PostalCode>
<PostalArea>Essex</PostalArea>
<Name />
<City>Colchester</City>
<Country>UK</Country>
</Invoice>
</Addresses>
<OrderStatus xmlns="http://24sevenOffice.com/webservices">Offer</OrderStatus>
<DateOrdered xmlns="http://24sevenOffice.com/webservices">2015-06-15T14:00:00Z</DateOrdered>
<PaymentTime xmlns="http://24sevenOffice.com/webservices">14</PaymentTime>
<IncludeVAT xsi:nil="true" xmlns="http://24sevenOffice.com/webservices" />
<OrderTotalIncVat xmlns="http://24sevenOffice.com/webservices">480.0000</OrderTotalIncVat>
<OrderTotalVat xmlns="http://24sevenOffice.com/webservices">80.0000</OrderTotalVat>
<Currency xmlns="http://24sevenOffice.com/webservices">
<Symbol>LOCAL</Symbol>
</Currency>
<TypeOfSaleId xmlns="http://24sevenOffice.com/webservices">-100</TypeOfSaleId>
<InvoiceRows xmlns="http://24sevenOffice.com/webservices">
<InvoiceRow>
<ProductId>18</ProductId>
<RowId>4665754</RowId>
<Price>400.0000</Price>
<Name>17" Laptop Screen</Name>
<DiscountRate>0.0000</DiscountRate>
<Quantity>7.0000</Quantity>
<Cost>0.0000</Cost>
<InPrice>0.0000</InPrice>
</InvoiceRow>
</InvoiceRows>
</InvoiceOrder>
The reason your code doesn't work is likely that you're ignoring the namespace of the elements you're looking for. There are many questions covering how to do that, such as this one.
That said, XmlDocument is a creaky old API and the newer LINQ to XML is a huge improvement - I'd suggest you look into that.
I'm also not sure the dictionary is pulling its weight for such a small number of elements. You can simply query what you need straight from the XML. For example, to get all your fields as typed values:
var doc = XDocument.Parse(strfile);
var order = doc.Elements("InvoiceOrder").Single();
XNamespace ns = "http://24sevenOffice.com/webservices";
var orderId = (int)order.Element(ns + "OrderId");
var customerId = (int)order.Element(ns + "CustomerId");
var customerName = (string)order.Element(ns + "CustomerName");
var orderStatus = (string)order.Element(ns + "OrderStatus");
var dateOrdered = (DateTime)order.Element(ns + "DateOrdered");
var paymentTime = (int)order.Element(ns + "PaymentTime");
var totalIncVat = (decimal)order.Element(ns + "OrderTotalIncVat");
var totalVat = (decimal)order.Element(ns + "OrderTotalVat");
var currency = (string)order.Elements(ns + "Currency").Elements(ns + "Symbol").SingleOrDefault();
var typeOfSaleId = (int)order.Element(ns + "TypeOfSaleId");
You can use a similar technique to get map your addresses to your strongly typed Address class:
var deliveryAddress = order.Elements(ns + "Addresses")
.Elements(ns + "Delivery")
.Select(e => new Invoice.Address
{
Street = (string)e.Element(ns + "Street"),
// ....
})
.Single();
The problem you have is with namespaces. If you specify the namespace for each of those elements then it seems to work. I came to this conclusion with a bit of googling and some experimentation so my explanation might not be spot on so I advise researching the issue further yourself to understand it correctly.
This code will work:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(inputXMLDoc.NameTable);
nsmgr.AddNamespace("ns", "http://24sevenOffice.com/webservices");
var oNodeList = importList["Addresses"].SelectNodes("//ns:Delivery/ns:Street",nsmgr);
The reason is (I think) that in your XML document you are specifying a default namespace for your elements (xmlns="http://24sevenOffice.com/webservices") and in your xpath you are not specifying that same namespace. In my code I create a namespace manager with that namespace in and prefix it to the two elements which it now considers to match the ones in your document that have these namespaces.

How to extract xml child element

I am trying to figure out the code to extract xml child (I think this is worded correctly) elements. I have searched and tried many samples but cannot find how to drill down to pick out the section I want and return the information I need. Maybe I all I need is someone to define the data I am trying to pull so I can read up on the issue, of course any code would be very helpful and I will figure it out from there. Thanks in advanced for any help!
Here is the xml file. I am trying to run an if statement to find the section named <STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE> and return the <JOBNAME>,<TIMEDELTA>,<VALUESUM>.
<?xml version="1.0" encoding="utf-8"?>
<PVCAPTURESTATISTICCONTAINTER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PVCAPTUREJOBSTATISTICS>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE>
<STATISTICNAME>Characters saved</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved_NoMM</STATISTICTYPE>
<STATISTICNAME>Characters saved (no match and merge)</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
</PVCAPTUREJOBSTATISTICS>
<DOCUMENTCOUNT>762</DOCUMENTCOUNT>
<PAGECOUNT>3194</PAGECOUNT>
<IMAGECOUNT>3194</IMAGECOUNT>
<VERSION>2.0</VERSION>
</PVCAPTURESTATISTICCONTAINTER>
You can use LINQ to XML, particularly the XElement class.
var element = XElement.Parse(xmlStr).Element("PVCAPTUREJOBSTATISTICS")
.Elements("PVCAPTURESTATISTICSUMMARY")
.First(c => c.Element("STATISTICTYPE").Value == "PVCAP_CharactersSaved")
var jobName = element.Element("JOBNAME").Value;
var timeDelta = element.Element("TIMEDELTA").Value;
var valueSum = element.Element("VALUESUM").Value;
You'll want to add in some error handling and whatnot here, but this should get you going in the right direction.
You can do something like this:
XElement res = XElement.Parse(xmlResult);
foreach(var elem in res.Element("PVCAPTUREJOBSTATISTICS").Elements("PVCAPTURESTATISTICSUMMARY"))
{
if (elem.Element("STATISTICTYPE").Value.Equals("PVCAP_CharactersSaved", StringComparison.Ordinal))
{
string jobName = elem.Element("JOBNAME").Value;
string timeDelta = elem.Element("TIMEDELTA").Value;
string valueSum = elem.Element("VALUESUM").Value;
}
}
You can use XDocument and LINQ-to-XML to do that quite easily, for example :
string xml = "your xml content here";
XDocument doc = XDocument.Parse(xml);
//or if you have the xml file instead :
//XDocument doc = XDocument.Load("path_to_xml_file.xml");
var result = doc.Descendants("PVCAPTURESTATISTICSUMMARY")
.Where(o => (string) o.Element("STATISTICTYPE") == "PVCAP_CharactersSaved")
.Select(o => new
{
jobname = (string) o.Element("JOBNAME"),
timedelta = (string) o.Element("TIMEDELTA"),
valuesum = (string) o.Element("VALUESUM")
});
foreach (var r in result)
{
Console.WriteLine(r);
}

Categories