How to get specific children of a xml element? - c#

I am loading a xml document and I am having a foreach loop in its elements and I want to select child elements named tag in it.
This is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<view>
<tag>
<name>content</name>
<tag>
<name>div</name>
</tag>
</tag>
</view>
And this is the code:
string xmlString = System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath("~/xml/xml.xml"));
XDocument doc = XDocument.Parse(xmlString);
XElement xmlElement = doc.Element("view");
foreach (var tagItem in xmlElement.Descendants("tag"))
{
//do something
}
The code written in foreach loop would contain all of tag elements in any depth, but I want to get the first depth ones(the children).
How to do this with linq?

Assuming the desired elements are always children of the <view> element you can use:
XElement xmlElement = doc.Element("view");
foreach (var tagItem in xmlElement.Elements("tag"))
{
//do something (only direct children)
}
There is nothing more to be done to get the desired elements. You can then however implement your "do something" with Linq, for example:
XElement firstElem = xmlElement.Elements("tag").OrderBy(e => e.Name).First();

Related

How to get nodes from XML file without its attribute and put to a List of string

I would like to display the tag names of child nodes without its attributes. Then those tag names (nodes) should be put in a List of string. Here's example of my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<CAR>
<ID>21</ID>
<MANUFACTURER>Ford</MANUFACTURER>
<MODEL>Fiesta</MODEL>
</CAR>
<CAR>
<ID>22</ID>
<MANUFACTURER>Peugeot</MANUFACTURER>
<MODEL>508</MODEL>
</CAR>
</ROOT>
So, the effect I want to get in a console output is shown below:
ID
MANUFACTURER
MODEL
Then I would like to store that ID, MANUFACTURER and MODEL tag names in a List of strings.
This is the code that I tried so far:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
try
{
xmlDocument.Load("XMLFile.xml");
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine(xmlDocument.OuterXml);
XmlNodeList nodeList = xmlDocument.SelectNodes("ROOT/CAR");
foreach(XmlNode node in nodeList)
{
Console.WriteLine(node.ChildNodes);
xmlNodes.Add(node.ChildNodes.ToString());
}
The problem is that it's not displaying the way I want to. As a result I only get two System.Xml.XmlChildNodes which seems to be corresponding to two <CAR> nodes, instead of its three child nodes, such as ID, MANUFACTURER and MODEL.
System.Xml.XmlChildNodes
System.Xml.XmlChildNodes
Adding items to a List basically adds the same thing as shown above.
What am I doing wrong?
If you have to use XmlDocument, then you can -
List<string> elements = new List<string>();
XmlNodeList CarNodes = xml.SelectNodes("Root/Car");
foreach(XmlNode c in CarNodes)
{
foreach(XmlNode n in c.ChildNodes)
{
if (!elements.Contains(n.Name))
{
elements.Add(n.Name);
}
}
}
But I find XDocument to be much simpler and better readability.
XDocument xdoc = XDocument.Parse(yourXmlString);
List<string> elements = xdoc.Descendants("Car")
.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).Distinct().ToList();
And thats all you'll need. Easy to read as well, get all the descendants of "Car" Node and get all distinct names of XElements within it.
Another way to do it -
List<string> elements = xdoc.Descendants("Car").First()
.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).ToList();
In this case I have removed the "distinct" and rather got just the first Car node ONLY. You can see the difference - if by any case some other Car node has an extra element, you'll miss getting that information by doing it this way.
You could loop through for children nodes:
1- You can define xmlNodes like a HashSet to avoid multiple tags like :
HashSet<string> xmlNodes = new HashSet<string>();
2 - Change little the code like :
....
XmlNodeList nodeList = xmlDocument.SelectNodes("ROOT/CAR");
foreach (XmlNode node in nodeList)
{
foreach(XmlNode element in node.ChildNodes)
{
if (element.NodeType == XmlNodeType.Element)
xmlNodes.Add(element.Name);
}
}
Demo
Console.WriteLine(string.Join(", ", xmlNodes));
Result
ID, MANUFACTURER, MODEL
I hope you find this helpful.

Iterating through XML file with XDocument returns element with no attributes

I'm iterating through all the child elements of this XML file:
<?xml version="1.0" encoding="utf-8"?>
<users>
<user name="SemiViral" access="2" />
</users>
with this code:
XDocument doc = XDocument.Load("Users.xml");
Console.WriteLine(doc.Descendants("users").Count());
foreach (XElement u in doc.Descendants("users")) {
Console.WriteLine(u.Attributes().Count());
}
but the output from the WriteLine is 0, and similarly empty if I try referencing the attributes directly. Counting the descendants returns 1 and when I added inner contents to the single child element, it was able to output those. So I know that it's the correct element, it's simply not accessing the attributes for some reason.
Here is a code to do what you are trying to do. You were not getting results because you were only looking for users elements (doc.Descendants("users")). The element that you are looking for is at the next level of the xml. If you debugged your code you would have spotted it.
XDocument doc = XDocument.Load("Users.xml");
Console.WriteLine(doc.Descendants("users").Descendants().Count());
foreach (XElement u in doc.Descendants("users").Descendants())
{
Console.WriteLine("value of the attribute is " + u.Attributes("access").First().Value);
}

Looping through all nodes in xml file with c#

I have an xml document with setup similiar to this:
<invoice>
<IssueDate>2015-09-07</IssueDate>
<InvoiceType>380<InvoiceType>
<AccountingSupplierParty>
<Party>
<EndpointID></EndpointID>
<PartyName>
<Name>Company test</Name>
</PartyName>
</Party>
</AccountingSupplierParty>
</invoice>
This is just a little piece of the entire xml document, just to show how the file looks.
I would like to check all the elements too see if they have empty values, such as EndpointID in this example (I need to replace empty values with NA).
This is what I have so far:
public static void AddToEmptyElements()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("testXml.xml");
XmlNodeList nodes = xmlDoc.DocumentElement.ChildNodes;
foreach (XmlNode node in nodes)
{
Console.WriteLine(node.Name);
}
}
However, this code will only loop through the childs of the root node and not all the grandchilds (or great grandchilds) such as the <Party> and <EndpointID> elements. How can I include these elements in the loop?
I'm not in an environment to test code right now, but isn't it possible to write a recursive method to loop further down the nodes?
Something like this (untested code):
private static void handleNode(XmlNode node)
{
if(node.HasChildNodes)
{
foreach(XmlNode child in node.ChildNodes)
{
handleNode(child);
}
}
else
Console.WriteLine(node.Name);
}
then call this method in place of your Console.WrintLine()
As Jon Skeet already said, you could do this using LINQ to XML.
XDocument xml = XDocument.Load(path);
var emptyElements = xml.Descendants().Where(xe => String.IsNullOrEmpty(xe.Value));
foreach (var xe in emptyElements)
xe.Value = "NA";

How to Remove Root Element in C#/

I'm new to XML & C#.
I want to remove root element without deleting child element.
XML file is strudctured as below.
<?xml version="1.0" encoding="UTF-8"?>
<dataroot generated="2013-07-06T20:26:48" xmlns:od="urn:schemas-microsoft-com:officedata">
<MetaDataSection>
<Name>KR04</Name>
<XMLCreationDate>02.05.2013 9:52:41 </XMLCreationDate>
<Address>AUTOMATIC</Address>
<Age>22</Age>
</MetaDataSection>
</dataroot>
I want to root element "dataroot", so it should look like below.
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataSection>
<Name>KR04</Name>
<XMLCreationDate>02.05.2013 9:52:41 </XMLCreationDate>
<Address>AUTOMATIC</Address>
<Age>22</Age>
</MetaDataSection>
Deleting child elements look like easy, but I don't know how to delete root element only.
Below is the code I've tried so far.
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load("path to xml");
XmlNodeList nodes = xmlFile.SelectNodes("//dataroot");
foreach (XmlElement element in nodes)
{
element.RemoveAll();
}
Is there a way to remove root element only? without deleting child elements?
Thank you in advnace.
Rather than trying to actually remove the root element from an existing object, it looks like the underlying aim is to save (or at least access) the first child element of the root element.
The simplest way to do this is with LINQ to XML - something like this:
XDocument input = XDocument.Load("input.xml");
XElement firstChild = input.Root.Elements().First();
XDocument output = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
firstChild);
output.Save("output.xml");
Or if you don't need the XML declaration:
XDocument input = XDocument.Load("input.xml");
XElement firstChild = input.Root.Elements().First();
firstChild.Save("output.xml");
if you need to do in c# coding means
Solution
foreach (XElement item in Element.Descendants("dataroot").ToList())
{
item.ReplaceWith(item.Nodes());
}

Get All node name in xml in silverlight

i created one xml like this
<names>
<name>
nixon
</name>
</names>
i want iterate each node name by foreach loop or any other loop in silverlight using xdocument.
how can i get this node name?
You can use the DescendantsAndSelf() method of XElement to get all the nodes and their names.
foreach (XElement child in doc.Root.DescendantsAndSelf())
{
Console.WriteLine(child.Name.LocalName);
}
DescendantsAndSelf() Returns a collection of elements that contain this element, and all descendant elements of this element, in document order.
With LinqToXml:
var xDoc = XDocument.Parse(mySmlString);
var names = xDoc.Root.Elements("name").Select(x=> x.Value.Trim()).ToArray();
foreach (var name in names)
{
System.Console.WriteLine(name);
}

Categories