HasChildNodes (.Net, XmlDocument ) always reported "true" - c#

I would like to distinguish these two cases - but HasChildNode returns in both cases "true" and the number of childNodes is 1 in both cases.
<eventid>45072</eventid>
<titles>
<title>kabel eins late news</title>
</titles>
Here ist my sample code and output.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
XmlNodeList xnList = doc.SelectNodes("/epg/programme");
foreach (XmlNode n in xnList) {
foreach (XmlNode n1 in n.ChildNodes) {
if (n1.HasChildNodes) {
AppendText($"n1 has {n1.ChildNodes.Count} ChildNodes");
foreach (XmlNode n2 in n1.ChildNodes) {
Append(41,n2.Name, n2.InnerText);
}
}
else {
// this will never called
Append(46,n1.Name, n1.InnerText);
}
}
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<epg Ver="1">
<programme>
<eventid>45072</eventid>
<titles>
<title>kabel eins late news</title>
</titles>
</programme>
</epg>
Output:
n1 has 1 ChildNodes
41:#text:45072
n1 has 1 ChildNodes
41:title:kabel eins late news

Thanks to #DavidBrowne-Microsoft I have changed my code to XDocument and a little bit Linq to XML
XDocument doc = XDocument.Parse(xmlString);
var programme = doc.Descendants("programme").Select(p => p);
foreach (XElement p in programme) {
foreach (var attr in p.Attributes()){
AppendText($"{attr.Name} {attr.Value}");
}
foreach (XElement ele in p.Elements()) {
if (ele.HasElements) {
foreach (XElement child in ele.Elements()) {
AppendText($"{child.Name} {child.Value}");
}
}
else {
AppendText($"{ele.Name} {ele.Value}");
}
}
}
I found only a few beginner examples so here is this snippet for the start.

Related

Loop through XML with XmlDocument

I'm new to using Linq and XMLDocument.
I have a simple XML file and I want to loop through all of the elements and print the tag and value. I don't want to use the XML Tags when looping through. this is what I have so far.
XML file:
<?xml version="1.0" encoding="UTF-8"?>
<Step1>One
<Step2>Two
<Step3>Three
<Step4>Four
</Step4>
</Step3>
</Step2>
</Step1>
C# Code
private void StartIt()
{
System.Xml.XmlDocument xd = new System.Xml.XmlDocument();
xd.Load(#"C:\Projects\GetXML\testLayers.xml");
XmlNodeList nl = xd.SelectNodes("Layer1");
foreach (XmlNode xnode in nl)
{
Console.WriteLine(xnode.Name + " = " + xnode.InnerText); // + " " + xnode.InnerXml);
}
}
Results:
Step1 = One
Two
Three
Four
What I want:
Step1 = One
Step2 = Two
Step3 = Three
Step4 = Four
Any suggestions?
With a little help of Linq,
XmlDocument doc = new XmlDocument();
doc.Load(fname);
var nodes = doc.SelectNodes("//*[text()]")
.Cast<XmlNode>()
.Select(n => new {
Name= n.Name,
Value = n.SelectSingleNode("text()").Value
})
.ToList();
// System.Xml.XmlDocument version
XmlDocument xd = new XmlDocument();
xd.Load(#"C:\Projects\GetXML\testLayers.xml");
foreach (XmlElement step in xd.SelectNodes("//*"))
{
Console.WriteLine("{0} = {1}", step.Name,
step.SelectSingleNode("text()").Value);
}
// System.Xml.Linq.XDocument version
XDocument xdLinq = XDocument.Load(#"C:\Projects\GetXML\testLayers.xml");
foreach (XElement step in xdLinq.XPathSelectElements("//*"))
{
Console.WriteLine("{0} = {1}", step.Name,
step.Nodes().Where(n => n.NodeType == XmlNodeType.Text).FirstOrDefault());
}
You can do the same using LINQ to XML and XDocument class:
var xDoc = XDocument.Load("Input.txt");
foreach (var e in xDoc.Descendants())
{
Console.WriteLine("{0} = {1}", e.Name, e.Nodes().OfType<XText>().First().Value.Trim());
}

randomly Select XML nodes with same names

I have this XML file:
<Main>
<QA>
<question>What is your favorite color?</question>
<!--pick random!-->
<answer>Blue</answer>
<answer>Red</answer>
<answer>Green</answer>
<answer>Yellow</answer>
</QA>
<QA>
<question>What is your favorite programming language?</question>
<!--pick random!-->
<answer>PHP</answer>
<answer>C#</answer>
<answer>Java</answer>
<answer>VB.Net</answer>
</QA>
I want when the user enter one of the question that specified in above xml file, program pick a random answer from nodes.
For example when user enters "What is your favorite programming language?" in TextBox,
program must generate PHP,C#,Java or VB.Net randomly.
this is my code but not correct:
XmlDocument xml = new XmlDocument();
xml.Load("QA.xml");
XmlNodeList xList = xml.SelectNodes("Main/QA");
foreach (XmlNode xn in xList)
{
string Question = xn["question"].InnerText;
if (Question == txtQuestion.Text)
{
XmlNodeList answerlist = xml.SelectNodes("Main/QA/answer");
foreach (XmlNode ans in answerlist)
{
Console.WriteLine(ans.InnerText);
}
}
}
Output:
Blue
Red
Green
Yellow
PHP
C#
Java
VB.Net
Please help.
Try this:
XmlDocument xml = new XmlDocument();
xml.Load("QA.xml");
XmlNodeList xList = xml.SelectNodes("Main/QA");
foreach (XmlNode xn in xList)
{
string Question = xn["question"].InnerText;
if (Question == txtQuestion.Text)
{
XmlNodeList answerlist = xn.SelectNodes("./answer");
foreach (XmlNode ans in answerlist
.Cast<XmlNode>()
.OrderBy(elem => Guid.NewGuid()))
{
Console.WriteLine(ans.InnerText);
}
}
}
using Linq To Xml,
Random rnd = new Random();
var xDoc = XDocument.Load("QA.xml");
var question = xDoc.Descendants("QA")
.First(d => d.Element("question").Value == txtQ.Text);
var answer = question.Elements()
.Skip(rnd.Next(0, question.Elements().Count()))
.First().Value;

How can I get node I want from XML

<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Fruits>
<Fruit>hahahaha</Fruit>
</Fruits>
</Root>
If I try this code,
string[] cFruitName; int i=0;
XmlDocument a= new XmlDocument();
a.LoadXml(getXML());
foreach (XmlNode xn in a)
{
cFruitName[i] = xn.Text;
i++;
}
but I am getting null for xn.Text.
All I want is to get values of fruit, like "hahahah" in this example.
Edit
I changed my XML now.
var xml = XDocument.Parse(getXML());
var fruits = xml.Descendants("fruit").Select(n => n.Value);
Console.WriteLine(string.Join(Environment.NewLine, fruits));
prints
hahahaha
use XPath for .net 2.0 version
XmlDocument xml = new XmlDocument();
xml.LoadXml(getXML());
XmlNodeList fruits = xml.SelectNodes("//fruit");
foreach (XmlNode fruit in fruits)
{
Console.WriteLine (fruit.InnerText);
}
prints the same
Try this:
string[] cFruitName; int i=0;
XmlDocument a= new XmlDocument();
a.LoadXml(getXML());
foreach (XmlNode xn in a.Where(x=>x.Text != null))
{
cFruitName[i] = xn.Text;
i++;
}
or
string[] cFruitName; int i=0;
XmlDocument a= new XmlDocument();
a.LoadXml(getXML());
foreach (XmlNode xn in a.Where(x=>x.Name == "fruit"))
{
cFruitName[i] = xn.Text;
i++;
}

C# How do I determine childnode level in xml

I need to remove elements in some xml files. How do I correctly ensure that I transverse through all childnodes to remove all element with a matching name. I have code such as:
string strFilename = #"D:\sample.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strFilename);
XmlNode parentNode;
parentNode = xmlDoc.DocumentElement;
foreach (XmlNode node1 in parentNode.ChildNodes)
{
foreach (XmlNode node2 in node1.ChildNodes)
{
if (node2.Name == "ElementNodeToDelete")
{
node2.ParentNode.RemoveChild(node2);
}
foreach (XmlNode node3 in node2.ChildNodes)
{
if (node3.Name == "ElementNodeToDelete")
{
node3.ParentNode.RemoveChild(node3);
}
foreach (XmlNode node4 in node3.ChildNodes)
{
if (node4.Name == "ElementNodeToDelete")
{
node4.ParentNode.RemoveChild(node4);
}
}
}
}
}
Is this a valid solution? How do I determine how many foreach loops to perform to ensure that all children are checked?
Thanks for your time in advance.
Recursion is your friend.
void DeleteNodes(XmlNode root, string deleteName)
{
foreach(XmlNode node in root.ChildNodes)
{
if (node.Name == deleteName)
{
root.RemoveChild(node);
}
else
{
DeleteNodes(node,deleteName);
}
}
}

Xml node reading for each loop

I am trying to loop through an Xml file and display the value for account in a message.
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var");
foreach (XmlNode no in nodeList)
{
XmlNode node = testDoc.SelectSingleNode("/details/row/var[#name='account']");
test.actual = node.Attributes["value"].Value;
MessageBox.Show(test.account);
}
The message box is currently displaying the first record repeatidly, how can I get to the next record?
Thanks for your input in advance.
You are repeatedly assigning node with the same element from testDoc. It is not clear what test.account is (perhaps a mistype for test.actual)?
no is the variable which will iterate the contents of nodeList - I imagine you intended to use that.
EDIT following edit of OP
Now you've shown us what nodeList is, I suspect you want to do something like this instead :
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var[#name='account']");
foreach (XmlNode no in nodeList)
{
test.actual = no.Attributes["value"].Value;
...
XmlDocument doc = new XmlDocument();
doc.Load("d:\\test.xml");
XmlNodeList node = doc.GetElementsByTagName("w:r");
foreach (XmlNode xn in node)
{
try
{
if (xn["w:t"].InnerText != null)
{
if (xn["w:t"].InnerText == "#")
{
string placeHolder = xn["w:t"].InnerText;
foreach (XmlNode a in node)
{
if (a["w:t"].InnerText != "#")
{
string placeHolder1 = a["w:t"].InnerText;
}
}
}
}
}
catch (Exception e)
{
Console.Write(e);
}
}
Here is the sample for parent node value to get information of the child nodes.here i am using the ReportItems ParentNode and Print only image child nodes.
xmldoc.Load(rdlFile);
StringBuilder sb=new StringBuilder();
XmlNode node = xmldoc.GetElementsByTagName("ReportItems")[0];
XmlNodeList list = node.ChildNodes;
atributes=new string[node.ChildNodes.Count];
int l = 0;
for (int j = 0; j < node.ChildNodes.Count; j++)
{
if (list[j].Name == "Image")
{
XmlAttributeCollection att = list[j].Attributes;
atributes[l] = att[0].Value.ToUpper();
}
l++;
}
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (searchText.Text.ToUpper() == atributes[i])
{
XmlNodeList lastlist = node.ChildNodes;
XmlNodeList endlist = lastlist[i].ChildNodes;
for (int k = 0; k < endlist.Count; k++)
{
sb.Append(endlist[k].Name+" - "+ endlist[k].InnerText);
sb.Append("\n"+"\n");
}
}
}
let me know if you have doubt..
Try this,
XmlDocument xdoc = new XDocument();
xdoc.Load("*/File/*");
string xmlcontents = xdoc.InnerXml;
var xpath = "(/details/row/var[#name='account'])";
XmlNodeList lists = xdoc.DocumentElement.SelectNodes(xpath);
foreach (XmlNode _node in lists)
{
string _nodeValue = _node.InnerText;
MessageBox.Show(_nodeValue);
}
Try the following:
//Create an xml reader;
XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(/*File Name here*/);
//Select the element with in the xml you wish to extract;
XmlNodeList _nodeList = _xmlDocument.SelectNodes("/details/row/var[#name='account']");
//Display the values in the node list to the screen;
foreach (XmlNode _node in _nodeList)
{
String _nodeValue = _node.InnerText.ToString();
MessageBox.Show(_nodeValue.ToString());
}
I'm not 100% sure, but you may need to use recursion. If not, it should just look like this:
XmlDocument doc = //etc..
foreach(XmlNode node in doc.ChildNodes)
{
if(node.Name == "account")
{
MessageBox.Show(node.Value);
}
}
You shouldn't spend time with reading the xml node by node. Try Deserialization:

Categories

Resources