Loop through XML with XmlDocument - c#

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());
}

Related

Can't figure out how to read xml data in Visual Studio C#

I'm not sure how to read out the data from a XML file.
The XML file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Lijsten>
<Lijst>
<Titel>Discipline</Titel>
<Waardes>Elektro</Waardes>
<Waardes>Mechanisch</Waardes>
<Waardes>Civiel</Waardes>
<Waardes>Proces</Waardes>
</Lijst>
<Lijst>
<Titel>Soort</Titel>
<Waardes>Tekening</Waardes>
<Waardes>Tekst doc</Waardes>
<Waardes>Afbeelding</Waardes>
</Lijst>
<Lijst>
<Titel>Afdruk</Titel>
<Waardes>Landscape</Waardes>
<Waardes>Portrait</Waardes>
</Lijst>
<Lijst>
<Titel>Kleur</Titel>
<Waardes>Kleur</Waardes>
<Waardes>Zwart</Waardes>
</Lijst>
<Lijst>
<Titel>Kader</Titel>
<Waardes>Aanwezig</Waardes>
<Waardes>Niet aanwezig</Waardes>
</Lijst>
</Lijsten>
I'm trying to create a radio-button menu for every "Lijst".
What I've got so far(not much):
XmlTextReader reader = new XmlTextReader("iniFile.xml");
while (reader.Read())
{
while (reader.ReadToFollowing("Lijst"))
{
while (reader.ReadToFollowing("Titel"))
{
}
}
}
If you don't want to read using XElement, you can use XmlDocument and XPath
Take a look at this example, to get all titles:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"C:\temp\inifile.xml");
XmlNodeList nodes = xdoc.SelectNodes("//Titel");
foreach (XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
or, to get all Lijst nodes and then iterate through them to get title and warde values
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"C:\temp\inifile.xml");
XmlNodeList nodes = xdoc.SelectNodes("//Lijst");
foreach (XmlNode node in nodes)
{
Console.WriteLine("this is List with title: " + node["Titel"].InnerText);
Console.WriteLine("it contains wardes: " + node["Titel"].InnerText);
XmlNodeList wardeNodes = node.SelectNodes("Waardes");
foreach (XmlNode wNode in wardeNodes)
{
Console.WriteLine(" - " + wNode.InnerText);
}
}
With XElement class and LinqToXML:
XElement xml = XElement.Parse(xml);
var buttons = xml.Element("Lijsten")
.Elements()
.Select(p => new { Titel = p.Element("Titel").Value })
.ToArray();

Not able to read XML string in C#

I have created a XML string and Looping that to get value. But its not entering in foreach loop. But in my other code same loop code is working.
my code is :
XML string:
<SuggestedReadings>
<Suggestion Text="Customer Centricity" Link="http://wdp.wharton.upenn.edu/book/customer-centricity/?utm_source=Coursera&utm_medium=Web&utm_campaign=custcent" SuggBy="Pete Fader�s" />
<Suggestion Text="Global Brand Power" Link="http://wdp.wharton.upenn.edu/books/global-brand-power/?utm_source=Coursera&utm_medium=Web&utm_campaign=glbrpower" SuggBy="Barbara Kahn�s" />
</SuggestedReadings>
Code Is:
string str = CD.SRList.Replace("&", "&");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(str);
XmlNode SuggestionListNode = xmlDoc.SelectSingleNode("/SuggestedReadings/Suggestion");
foreach (XmlNode node in SuggestionListNode)
{
COURSESUGGESTEDREADING CSR = new COURSESUGGESTEDREADING();
var s = db.COURSESUGGESTEDREADINGS.OrderByDescending(o => o.SRID);
CSR.SRID = (s == null ? 0 : s.FirstOrDefault().SRID) + 1;
CSR.COURSEID = LibId;
CSR.TEXT = node.Attributes.GetNamedItem("Text").Value;
CSR.LINK = node.Attributes.GetNamedItem("Link").Value; ;
CSR.SUGBY = node.Attributes.GetNamedItem("SuggBy").Value; ;
CSR.ACTIVEFLAG = "Y";
CSR.CREATEDBY = CD.CreatedBy;
CSR.CREATEDDATE = DateTime.Now;
db.COURSESUGGESTEDREADINGS.Add(CSR);
}
You should use SelectNodes, not SelectSingleNode, since you are trying to get multiple rows out of the XML document.
Use this:
XmlNodeList SuggestionListNode = xmlDoc.SelectNodes("//Suggestion");
foreach (XmlNode node in SuggestionListNode)
{
}
You can try this.
XDocument xdoc = XDocument.Load("data.xml");
var xmlData = from lv1 in xdoc.Descendants("Suggestion")
select new {
Text = lv1.Attribute("Text").Value,
Link = lv1.Attribute("Link").Value,
SuggBy = lv1.Attribute("SuggBy").Value
};
foreach (var item in xmlData){
// your logic here
}

XML to string (C#)

I have a XML loaded from a URL like this:
WebClient client = new WebClient();
client.Encoding = Encoding.UTF8;
try
{
string reply = client.DownloadString("http://Example.com/somefile.xml");
label1.Text = reply;
}
catch
{
label1.Text = "FAILED";
}
That XML belongs to a RSS Feed. I want that label1.Text shows just the titles of that XML. How can I achieve that?
Example of label1.Text
This is my first title - This is my 2nd title - And this is my last title
You can load your XML into an XmlDocument and then use XPath to Get the value of each node you're targeting.
XmlDocument doc = new XmlDocument();
doc.LoadXml(reply);
XmlNodeList nodes = doc.SelectNodes("//NodeToSelect");
foreach (XmlNode node in nodes)
{
//If the value you want is the content of the node
label1.Text = node.InnerText;
//If the value you want is an attribute of the node
label1.Text = node.Attributes["AttibuteName"].Value;
}
If you are not familiar with XPath you can always check here :
http://www.w3schools.com/xpath/xpath_syntax.asp
var xml= XElement.Parse(reply);
label1.Text = string.Join(Environment.NewLine, xml
.Descendants()
.Where (x => !string.IsNullOrEmpty(x.Value))
.Select(x=> string.Format("{0}: {1}", x.Name, x.Value))
.ToArray());
You probably need to parse the RSS XML manually to get the title. Here is some sample code for your reference:
private static List<FeedsItem> ParseFeeds(string feedsXml)
{
XDocument xDoc = XDocument.Parse(feedsXml);
XNamespace xmlns = "http://www.w3.org/2005/Atom";
var items = from entry in xDoc.Descendants(xmlns + "entry")
select new FeedsItem
{
Id = (string)entry.Element(xmlns + "id").Value,
Title = (string)entry.Element(xmlns + "title").Value,
AlternateLink = (string)entry.Descendants(xmlns + "link").Where(link => link.Attribute("rel").Value == "alternate").First().Attribute("href").Value
};
Console.WriteLine("Count = {0}", items.Count());
foreach(var i in items)
{
Console.WriteLine(i);
}
return null;
}

How to update the XMLDocument using c#?

I want to update the xml document and i need to return the updated xml in string. I am trying like below. when i save the document it expects the file name. but i dont want to save this as file. i just want to get the updated xml in string.
string OldXml = #"<Root>
<Childs>
<first>this is first</first>
<second>this is second </second>
</Childs
</Root>";
XmlDocument NewXml = new XmlDocument();
NewXml.LoadXml(OldXml );
XmlNode root = NewXml.DocumentElement;
XmlNodeList allnodes = root.SelectNodes("*");
foreach (XmlNode eachnode in allnodes)
{
if (eachnode.Name == "first")
{
eachnode.InnerText = "1";
}
}
NewXml.Save();
string newxml = NewXml.OuterXml;
You don't need to call Save method because string is immutable, your problem is in root.SelectNodes("*"), it just get child nodes, not all level of nodes. You need to go one more level:
foreach (XmlNode eachnode in allnodes)
{
var firstNode = eachnode.ChildNodes.Cast<XmlNode>()
.SingleOrDefault(node => node.Name == "first");
if (firstNode != null)
{
firstNode.InnerText = "1";
}
}
string newxml = NewXml.OuterXml;
It would be strongly recommended using LINQ to XML, it's simpler:
var xDoc = XDocument.Parse(OldXml);
foreach (var element in xDoc.Descendants("first"))
element.SetValue(1);
string newXml = xDoc.ToString();
Your iteration never reaches a node called "first". Else it would work fine without saving the NewXml.
You could however use a XElement and iterate over all descendants.
string OldXml = #"<Root>
<Childs>
<first>this is first</first>
<second>this is second </second>
</Childs>
</Root>";
var NewXml = XElement.Parse(OldXml);
foreach (var node in NewXml.Descendants())
{
if (node.Name.LocalName == "first")
{
node.Value = "1";
}
}
var reader = NewXml.CreateReader();
reader.MoveToContent();
string newxml = reader.ReadInnerXml();

how to determine count of tag

I have a bit of xml file named Sample.xml which is shown below
<?xml version="1.0" encoding="ISO-8859-1"?>
<countries>
<country>
<text>Norway</text>
<value>N</value>
</country>
<country>
<text>Sweden</text>
<value>S</value>
</country>
<country>
<text>France</text>
<value>F</value>
</country>
<country>
<text>Italy</text>
<value>I</value>
</country>
</countries>
i have button named submit(button1).If i click that button i need to display the count(PartitionName="AIX") in a text box named textBox1, means How many PartitionName="AIX" is belonging to Type="NIC"
Can any one give me the c# code
I did like this,,but not able to get the answaer
private void button1_Click(object sender, EventArgs e)
{
XmlDocument doc1 = new XmlDocument();
doc1.Load(#"D:\New Folder\WindowsFormsApplication3\WindowsFormsApplication3\Sample.xml");
XmlNodeList a = doc1.GetElementsByTagName("AIX");
textBox1.Text = a.Count.ToString();
}
here is a quick soln I arrived at using linq. hope you find it useful.
static void Main(string[] args)
{
XElement xElement = XElement.Load(#"C:\Labs\test.xml");
// PartitionName="AIX" is belonging to Type="NIC"
var count = xElement.Descendants().Where(x => x.Name.ToString().Contains("Port")) // namespaces might be used here for faster traversal..
.Where(x => x.HasAttributes && x.Attribute("Type").Value == "NIC")
.Descendants().Where(x => x.Name.ToString().Contains("Client"))
.Where(x => x.Attribute("PartitionName").Value == "AIX").Count();
string str = count.ToString();
Console.WriteLine("Count = {0}", str);
Console.ReadLine();
}
Using xpath something like this:
count(vendor/Slot/Port[#Type='NIC']/Client[#PartitionName='AIX'])
But you have to modify it to support your namespaces.
Also easier and shorter code than going the Linq route for this particular case.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("inv", "http://secon.com/Ultravendor");
int count = doc.SelectNodes("inv:vendor/inv:Slot/inv:Port[#Type='NIC']/inv:Client[#PartitionName='AIX']", nsMgr).Count;
XmlDocument doc1 = new XmlDocument();
doc1.Load(#"C:\Labs\test.xml");
XmlNodeList nodes = doc1.GetElementsByTagName("inv:Port");
int count = 0;
foreach (XmlNode childNode in nodes)
{
XmlNodeReader nodeReader = new XmlNodeReader(childNode);
while (nodeReader.Read())
{
if (nodeReader.GetAttribute("PartitionName") == "AIX")
{
count++;
}
}
}
Console.WriteLine("Count = {0}", count);
Console.ReadLine();

Categories

Resources