How to get specific element Count in XML or XElement variable - c#

Consider this XML:
<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>
I declare a XElement variable and create the XML assigning it to that. How I can get count of ID elements in this XML variable in C#?

Prerequisite: in order to use .Count() you need to import the namespace System.Linq:
using System.Linq;
You can filter the descendant elements using the Descendants method with the name "ID", then count the results:
int count = xml.Descendants("ID").Count();
Be aware that Descendants looks through all levels. If you had an element other than Person that also had an ID child element, you would want to be more specific. In that case, to count ID child elements that belong to Person elements, you would use:
int count = xml.Elements("Person")
.Elements("ID")
.Count();

XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(XmlPath);
var totalItems = xmldoc.SelectNodes(
"/root/node/LastName/").Count;

var cnt = element.Descendants("ID").Count();

Related

How to store inner text of nodes with same names to a List?

Using C#, I need to store all the data of the inner text of Email nodes into a list, and all the data of the inner text of Related nodes into a list for each person separately. For now I was only able to store only first "email" node and first "related" node into lists. I get this:
,when I should get this
.
How to get the right answer? This is my xml file:
<? xml version="1.0" encoding="utf-8"?>
<People>
<Person>
<Name>Toni</Name>
<Email>a#g.c</Email>
<Email>b#g.c</Email>
<Email>c#g.c</Email>
<Related>Friend1</Related>
<Related>Friend2</Related>
</Osoba>
<Osoba>
<Name>Deni</Name>
<Email>d#g.c</Email>
<Email>e#g.c</Email>
<Email>f#g.c</Email>
<Related>Friend3</Related>
<Related>Friend4</Related>
</Osoba>
</People>
I am assuming the following xml Instead of the one you posted since it is wrong.
<?xml version="1.0" encoding="utf-8"?>
<People>
<Person>
<Name>Toni</Name>
<Email>a#g.c</Email>
<Email>b#g.c</Email>
<Email>c#g.c</Email>
<Related>Friend1</Related>
<Related>Friend2</Related>
</Person>
<Person>
<Name>Deni</Name>
<Email>d#g.c</Email>
<Email>e#g.c</Email>
<Email>f#g.c</Email>
<Related>Friend3</Related>
<Related>Friend4</Related>
</Person>
</People>
I am using LINQ to XML.(Another way is to use XmlDocument)
String path = "Path of your xml file";
XDocument doc = XDocument.Load(path);
var nodes = doc.Descendants("Person");
foreach (XElement node in nodes)
{
var name = node.Element("Name").Value;
var emails = node.Elements("Email").Select(x => x.Value);
}

C# XML Read All Child Nodes Of A Specific Node

So I have a program that reads all the name nodes in a XML file and adds these to a Combo Box. On a button click, it then takes this response and needs to get all the other data from the child nodes of the node the name is in.
The XML document:
<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>
What I've got so far:
XmlDocument Doc = new XmlDocument();
Doc.Load(FilePath);
foreach (XmlNode Node in Doc.SelectNodes("People/Person"))
{
comboBox1.Items.Add(Node.SelectSingleNode("Name").InnerText);
}
string RegPicked = comboBox1.SelectedItem.ToString();
foreach (XmlNode xNode in Doc.SelectNodes("People/Person"))
if (xNode.SelectSingleNode("Name").InnerText == RegPicked)
{
textBox1.Text = xNode.ParentNode.ChildNodes.ToString();
}
Doc.Save(FilePath);
When I run the code I just get "System.Xml.XmlChildNodes" in the text box.
I know I've done something wrong but I'm not sure what.
you have to distinguished child node:
textBox1.Text = xNode.ParentNode.ChildNodes.SelectSingleNode("age").InnerText;
Do this, you will get all the elements inside the parent of the node you are searching the value of.
string str = #"<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>";
XDocument xdoc = XDocument.Parse(str);
var xmlURL = (from el in xdoc.Descendants("Name")
where el.Value == "John"
select el.Parent).First().ToString();

validating an xml and finding line and column of error

i have an xml document of this kind
<xml>
<person name="a">
<age>21</age>
<salary>50000></salary>
</person>
<person name="b">
<age>25</age>
<salary>30000></salary>
</person>
<person name="c">
<age>30</age>
<salary>60000></salary>
</person>
<person name="d">
<age>35</age>
<salary>150000></salary>
</person>
</xml>
Now im trying to validate this document by passing this to a method like this
validate(string file)
{
// here i have some logic
// say i am trying to check if the salary is >50000 and age > 30
// if it doesn't satisfy the condition i have to return an error
}
I am able to achieve this . What i really want is to know where exactly the error in xml document is , like which line and column.
How should i do this ? any suggestions?
You are closing your 'age' tag like this
<age>35<age/>
It should be like
<age>35</age>
hope this works for you.
Firstly, you have not specified how you are parsing your XML in c#. It matters.
Now as for validity of your XML document, a valid xml document should have these:
XML documents must have a root element
XML elements must have a closing tag
XML tags are case sensitive
XML elements must be properly nested
-XML attribute values must be quoted
now try adding this to the top of your xml doc
<?xml version="1.0" encoding="ISO-8859-1"?>
Now, to parse XML document, you can use either XmlDocument class or Linq's XDocument class.
Lets take example of XmlDocument.
if you have a xml string, load Xml as below:
XmlDocument doc = new XmlDocument();
doc.LoadXml(stringXML);
foreach(XmlNode node in doc.SelectNodes("xml/person/salary"))
{
var strSalary = node.InnerText;
var intSalary = Convert.ToInt32(strSalary??0);
}
if you have a xml file, load Xml as below:
XmlDocument doc = new XmlDocument();
doc.Load(XMLFilePath);
Full example:
string xml = #"<xml>
<person name=""a"">
<age>21</age>
<salary>50000</salary>
</person>
<person name=""b"">
<age>25</age>
<salary>30000</salary>
</person>
<person name=""c"">
<age>30</age>
<salary>60000</salary>
</person>
<person name=""d"">
<age>35</age>
<salary>150000</salary>
</person>
</xml>";
using (var sr = new StringReader(xml))
{
var xml2 = XDocument.Load(sr, LoadOptions.SetLineInfo);
foreach (var person in xml2.Root.Elements())
{
//string name = (string)person.Attribute("name"); // Unused
int age = (int)person.Element("age");
int salary = (int)person.Element("salary");
// Your check
bool error = salary > 50000 && age > 30;
if (error)
{
// IMPORTANT PART HERE!!!
int lineNumber = -1;
int colNumber = -1;
var lineInfo = (IXmlLineInfo)person;
if (lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
colNumber = lineInfo.LinePosition;
}
return string.Format("Error on line {0}, col {1}", lineNumber, colNumber);
// END IMPORTANT PART!!!
}
}
}
The "trick" is that XElement implement IXmlLineInfo (as explained here), but you have to load the document with LoadOptions.SetLineInfo.

How to count the childnodes for the specific node in the XML document?

I'm fresher to c#. i've to parse the xml document and have to count the specific node of the childnodes.
e.g:
<Root>
<Id/>
<EmployeeList>
<Employee>
<Id/>
<EmpName/>
</Employee>
<Employee>
<Id/>
<EmpName/>
</Employee>
<Employee>
<Id/>
<EmpName/>
</Employee>
</EmployeeList>
</Root>
In this xml, how do I count the "Employee" nodes??
How can i parse and get the solution using XmlDocument class in C#?
int Count = doc.SelectNodes("Employee").Count;
You can use XPath
var xdoc = XDocument.Load(path_to_xml);
var employeeCount = (double)xdoc.XPathEvaluate("count(//Employee)");
Using linq to xml you can do:
XElement xElement = XElement.Parse(xml);
int count = xElement.Descendants("Employee").Count();
This assumes you have your xml in the string xml.
XmlDocument doc = new XmlDocument();
doc.LoadXml(XmlString);
XmlNodeList list = doc.SelectNodes("Root/EmployeeList/Employee");
int numEmployees = list.Count;
if the xml is from a file, use
doc.Load(PathToXmlFile);
I would highly recommend using the System.Xml.Linq library instead. it is much better than the one you are trying to use. Once you have loaded your XDocument, you can just get the root node and do something along the lines of:
//Parse the XML into an XDocument
int count = 0;
foreach(XElement e in RootNode.Element("EmployeeList").Elements("Employee"))
count++;
This code isn't exact, but you can look here for more complex examples:
http://broadcast.oreilly.com/2010/10/understanding-c-simple-linq-to.html

Parsing Optional Tags in C#

I'm trying to find an easy and slick way to do the following requirement.
I have a XML message with this arrangement:
<persons>
<person>
<firstName>Mike</firstName>
<middleName>K.</middleName>
<lastName>Kelly</lastName>
</person>
<person>
<firstName>Steve</firstName>
<lastName>David</lastName>
</person>
<person>
<firstName>Laura</firstName>
<middleName>X.</middleName>
<lastName>Xavier</lastName>
</person>
</persons>
I want to parse this XML using xPath expressions.
persons/person/firstName
persons/person/middleName
persons/person/lastName
My objective is store firstName, middleName and lastName tag values like this into a list of string objects like this:
firstNameList[0] = "Mike";
firstNameList[1] = "Steve";
firstNameList[2] = "Laura";
middleNameList[0] = "K.";
middleNameList[1] = null;
middleNameList[2] = "X.";
lastNameList[0] = "Kelly";
lastNameList[1] = "David";
lastNameList[2] = "Xavier";
In my C# code, I do this:
XmlNodeList firstNameNodeList = xmlDoc.SelectNodes("persons/person/firstName", nsmgr);
XmlNodeList middleNameNodeList = xmlDoc.SelectNodes("persons/person/middleName", nsmgr);
XmlNodeList lastNameNodeList = xmlDoc.SelectNodes("persons/person/lastName", nsmgr);
The problem with this code is that for middle name, I don't have it for 2nd person in my XML list. So the middleNameNodeList returns 2 values (K. and X.) but I wouldn't know whether the 1st or 2nd or 3rd person's middle name is missing.
I was hoping that SelectNodes() API would provide an iteration or index ID as which repeating element has a given value.
Please suggest me an easiest way to achieve what I needed? Thanks so much for your help, JK
How about this?
foreach (Node person in xmlDoc.SelectNodes("persons/person", nsmgr))
{
firstNameNodeList.Add(person.SelectSingleNode("firstName", nsmgr));
middleNameNodeList.Add(person.SelectSingleNode("middleName", nsmgr));
lastNameNodeList.Add(person.SelectSingleNode("lastName", nsmgr));
}
Intead of getting a list of names, try getting a list of persons, then iterate the list and get their names.
You just have to iterate over persons/person and handle each individually - this would work:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"test.xml");
var persons = xmlDoc.SelectNodes("persons/person");
foreach (XmlNode person in persons)
{
string firstName = person.SelectSingleNode("firstName").InnerText;
string middleName = (person.SelectSingleNode("middleName") != null)
? person.SelectSingleNode("middleName").InnerText
: null;
string lastName = person.SelectSingleNode("lastName").InnerText;
}
Try
<persons>
<person>
<firstName>Mike</firstName>
<middleName>K.</middleName>
<lastName>Kelly</lastName>
</person>
<person>
<firstName>Steve</firstName>
<middleName />
<lastName>David</lastName>
</person>
<person>
<firstName>Laura</firstName>
<middleName>X.</middleName>
<lastName>Xavier</lastName>
</person>
</persons>
<person>
<firstName>Steve</firstName>
<middleName />
<lastName>David</lastName>
</person>
this should return "K","","X" for InnnerText

Categories