how to check whether child node is there for the product node in the following xml:
<product>
<SysSectionName>Processors</SysSectionName>
<section>
<subsection>
<SysSectionName>CPU#1</SysSectionName>
</subsection>
</section>
</product>
I have tried this:
foreach (XmlNode xn1 in sectionNode)
{
XmlNode node = xn1.FirstChild;
if (xn1.HasChildNodes)
{
//do something..
}
}
XmlNodeList snode = xmldoc.SelectNodes("/product/section/subsection");
foreach (XmlNode xn2 in snode)
{
//it comes inside if there will be a child node.
}
Try to use this piece of code to get the product nodes from XML:
XDocument doc = XDocument.Parse("Your Xml String");
var products = doc.Descendants("product");
foreach (var product in products)
{
//... do something ...
}
You mean you want to find whether product node has any child node?
If yes,
XmlNodeList productNodes = xmlDoc.SelectNodes("Product");
foreach(XmlNode pNode in productNodes)
{
if(pNode.ChildNodes.count >0)
{
}
}
I think XLinq (Linq for Xml) is what you're looking for.
Then you should load the Xml using XDocument, and for any XElement you have the "Descendants()" method, which returns list of child XElements. If there are no child elements, the list will have no elements as well.
Related
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.
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";
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();
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);
}
This removes all elements from the document:
XDocument document = XDocument.Load(inputFile);
foreach (XElement element in document.Elements())
{
element.Remove();
}
document.Save(outputFile);
This doesn't have any effect:
XDocument document = XDocument.Load(inputFile);
foreach (XElement element in document.Elements())
{
//element.Remove();
foreach (XElement child in element.Elements())
child.Remove();
}
document.Save(outputFile);
Am I missing something here? Since these are all references to elements within the XDocument, shouldn't the changes take effect? Is there some other way I should be removing nested children from an XDocument?
Thanks!
Apparently when you iterate over element.Elements(), calling a Remove() on one of the children causes the enumerator to yield break. Iterating over element.Elements().ToList() fixed the problem.
Here's an example of another way using System.Xml.XPath (change the xpath query to suit your needs):
const string xml =
#"<xml>
<country>
<states>
<state>arkansas</state>
<state>california</state>
<state>virginia</state>
</states>
</country>
</xml>";
XDocument doc = XDocument.Parse(xml);
doc.XPathSelectElements("//xml/country/states/state[.='arkansas']").ToList()
.ForEach(el => el.Remove());;
Console.WriteLine(doc.ToString());
Console.ReadKey(true);
When using XDocument try this instead:
XDocument document = XDocument.Load(inputFile);
foreach (XElement element in document.Elements())
{
document.Element("Root").SetElementValue(element , null);
}
document.Save(outputFile)
Regards,
Todd