how to determine count of tag - c#

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

Related

How do I get a specific element in a XML document?

I have a XML file that looks like this:
<Info>
<ID>1</ID>
<Result>
<ID>2</ID>
</Result>
</Info>
I want to count how many Info/Result/ID I have in this file.
I am doing this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("myFile.xml");
xmlNodeList MyList = xmlDoc.GetElementsByTagName("Info/Result/ID");
int totalCount = MyList.Count;
// other logic...
The method GetElementsByTagName does not find any "ID"-field.
I want to get the "ID = 2".
How do I do that?
To count all the nodes in "Info/Result/ID" path use this..
var count = xmlDoc.SelectNodes("Info/Result/ID")?.Count ?? 0;
To process these nodes
var nodes = xmlDoc.SelectNodes("Info/Result/ID");
foreach (XmlNode node in nodes) {
var idValue = node.InnerText
// do something
}
Got it working, hereĀ“s how:
public static void MyCountExample(string myXml, out int myID)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(myXml ?? ""));
var reader = XmlReader.Create(stream);
myID= 0;
reader.IsStartElement("Info");
while (!reader.EOF)
{
if (reader.ReadToFollowing("Result"))
{
if (reader.ReadToDescendant("ID"))
{
myID++;
else
{
return somethingElse();
}
......

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

Want to save particular node into the Xml File using c#

code below:
protected void generate_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("XmlFileName");
XmlNode node = doc.SelectSingleNode("ChartData/XaxisFields/XaxisField");
if (node != null)
{
node.ChildNodes.Item(0).InnerXml = "hi";
doc.Save("XmlFileName");
}
}
Showing null refernce here,
node.ChildNodes.Item(0).InnerXml = "hi";
Is the code is correct,the code behind running not showing any error
but the Xaxisfield is not added.
<?xml version="1.0" encoding="utf-8" ?>
<ChartData>
<XaxisFields>
<XaxisField></XaxisField>
</XaxisFields>
</ChartData>
List item
I want to add the childnode Xaxisfield in the xml file by selcting the particular parent node
You can use Linq to Xml to select your node and update its value:
var xdoc = XDocument.Load("XmlFileName");
xdoc.Root.Element("XaxisFields").Element("XaxisField").Value = "hi";
// OR
// xdoc.XPathSelectElement("//XaxisField").Value = "hi";
xdoc.Save("XmlFileName");
Also your code is not working because there is no child nodes of XaxisField node. This will work:
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("XmlFileName");
XmlNode node = doc.SelectSingleNode("ChartData/XaxisFields/XaxisField");
if (node != null)
{
node.InnerXml = "hi";
doc.Save("XmlFileName");
}

Find all the child node of specific value in C#

<main>
<myself>
<pid>1</pid>
<name>abc</name>
</myself>
<myself>
<pid>2</pid>
<name>efg</name>
</myself>
</main>
that is my XML file named simpan. I have two button. next and previous. What i want to do is, all the info will shows off on the TextBox when the user click the button. The searching node will be based on the pid.
Next button will adding 1 value of pid (let's say pid=2) and it will search on the node that have the same value of pid=2. it also will show the name for the pid=2. (showing name=abc)
Same goes to the previous button where it will reduce 1value of pid (pid=1).
Does anybody knows how to do this?
//-------------EDIT------------------
thanks to L.B, im trying to use his code. however i got an error.
is my implementation of code correct?
private void previousList_Click(object sender, EventArgs e)
{
pid = 14;
XDocument xDoc = XDocument.Parse("C:\\Users\\HDAdmin\\Documents\\Fatty\\SliceEngine\\SliceEngine\\bin\\Debug\\simpan.xml");
var name = xDoc.Descendants("myself")
.First(m => (int)m.Element("PatientID") == pid)
.Value;
textETA.Text = name;
////////////////////
}
int pid = 2;
XDocument xDoc = XDocument.Parse(xml); //Load
var name = xDoc.Descendants("myself")
.First(m => (int)m.Element("pid") == pid)
.Element("name")
.Value;
You can use the following XPath to list all Myself tags, then look for what you want using a simple Linq command:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "file1.xml");
var resNodes = xmlDoc.SelectNodes("//myself");
XmlNode res = null;
var val = textBox1.Text;
var item = from XmlNode x in resNodes
select x;
foreach (var nodP in item) {
foreach (XmlNode nod in nodP.ChildNodes) {
if (nod.InnerText == val) {
res = nodP;
}
}
}
if (res == null)
// not found!
;
else
// show the result
;
Call me old fashioned but you could use an XPath, for example:
string xml =
#"<main>
<myself>
<pid>1</pid>
<name>abc</name>
</myself>
<myself>
<pid>2</pid>
<name>efg</name>
</myself>
</main>";
using System.Xml;
....
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
// Replace "2" in the string below with the desired pid
XmlNode xmlNode =
xmlDocument.DocumentElement.SelectSingleNode("myself/name[../pid=2]");
// xmlNode contains the <name>efg</name> XmlElement. For example:
string name = xmlNode.Value;
If it can match multiple nodes, for example there could be multiple <myself> elements with a child element <pid> set to 2, use the following instead:
foreach(XmlNode xmlNode in
xmlDocument.DocumentElement.SelectNodes("myself/name[../pid=2]"))
{
// xmlNode contains the matching <name> element
}
In both cases, the value can be extracted from the XmlNode using the Value property.
public class simpman
{
private static XElement root = XElement.Load("Simpman.xml");
public static string GetItem(int index)
{
XElement item =
(from element in root.Elements("myself")
where (int)element.Element("pid") == index
select element.Element("name")).SingleOrDefault();
return item != null ? item.Value : "Please check the Index";
}
}
Initialize a static itemIndex to 1 and use it further like itemIndex++ (for Next) and itemIndex-- (for Prev).
private void previousList_Click(object sender, EventArgs e)
{
pid = 14;
XDocument xDoc = XDocument.Load(#"C:\Users\HDAdmin\Documents\Fatty\SliceEngine\SliceEngine\bin\Debug\simpan.xml");
var name = xDoc.Root
.Descendants("myself")
.FirstOrDefault(e => e.Element("pid")
.Value
.Equals(pid.ToString(CultureInfo.InvariantCulture)))
.Element("name")
.Value;
textETA.Text = name;
}
XmlDocument doc = new XmlDocument();
FileStream fs = new FileStream(rootXMLPath, FileMode.Open, FileAccess.Read);
doc.Load(fs);
XmlNode node = doc.DocumentElement;
nodeName = "/main/myself";
var child1 = node.SelectSingleNode(nodeName).ChildNodes[0].FirstChild.InnerXml;
var child2 = node.SelectSingleNode(nodeName).ChildNodes[0].LastChild.InnerXml;
var child3 = node.SelectSingleNode(nodeName).ChildNodes[1].FirstChild.InnerXml;
var child4 = node.SelectSingleNode(nodeName).ChildNodes[1].LastChild.InnerXml;

How can I get all text nodes from XML file

I want to get all text nodes from an XML file.
How can I do this?
Example Input:
<root>
<slide>
<Image>hi</Image>
<ImageContent>this</ImageContent>
<Thumbnail>is</Thumbnail>
<ThumbnailContent>A</ThumbnailContent>
</slide>
</root>
Expected Output:
hi this is A
The only solution (so far) to enumerate all text nodes in any xml, regardless of its structure:
string input = #"
<root>
<slide>
<Image>hi</Image>
<ImageContent>this</ImageContent>
<Thumbnail>is</Thumbnail>
<ThumbnailContent>A</ThumbnailContent>
</slide>
</root>";
foreach (XText text in (IEnumerable)XDocument.Parse(input).XPathEvaluate("//*/text()"))
{
Console.WriteLine(text.Value);
}
EDIT: if you want to load xml from file then use XDocument.Load instead.
This code will print the inner text of all xml nodes which doesnt have a child:
static void Main(string[] args)
{
XmlDocument x = new XmlDocument();
x.Load("exp.xml");
PrintNode(x.DocumentElement);
}
private static void PrintNode(XmlNode x)
{
if (!x.HasChildNodes)
Console.Write(string.Format("{0} ", x.InnerText));
for (int i = 0; i < x.ChildNodes.Count; i++)
{
PrintNode(x.ChildNodes[i]);
}
}
On your example XML it will result in the output you want :)
You can try this:
string input = #"
<root>
<slide>
<Image>hi</Image>
<ImageContent>this</ImageContent>
<Thumbnail>is</Thumbnail>
<ThumbnailContent>A</ThumbnailContent>
</slide>
</root>";
XDocument doc = XDocument.Parse(input);
//You can also load data from file by passing file path to Load method
//XDocument doc = XDocument.Load("Data.xml");
foreach(var slide in doc.Root.Elements("slide"))
{
var words = slide.Elements().Select(el => el.Value);
string s = String.Join(" ", words.ToArray());
}
This will work
static void Main(string[] args)
{
XDocument xmlSkuDescDoc = XDocument.Parse
(#"<root>
<slide>
<Image>hi</Image>
<ImageContent>this</ImageContent>
<Thumbnail>is</Thumbnail>
<ThumbnailContent>A</ThumbnailContent>
</slide>
</root> "
);
var result = (from data in xmlSkuDescDoc.Descendants("slide")
select data).Elements().Select(i => i.Value).Aggregate((a, b) => a + " " + b);
Console.ReadKey();
}
N.B.~ use XDocument.Load(filename) if loading from file
e.g.
string fileName = #"D:\MyXml.xml";
XDocument xmlSkuDescDoc = XDocument.Load(filename);
.... and the rest follows as shown above
It can be done using XDocument class (LINQ to XML). Assuming that you have exactly one slide element:
Using plain XDocument navigation:
var doc = XDocument.Load("file path here");
if (doc.Root == null)
throw new ArgumentException(); // No root node!
var slideElement = doc.Root.Element("slide");
if (slideElement == null)
throw new ArgumentException(); // No slide node!
var values = string.Join(" ", slideElement.Elements().Select(element => element.Value));
Using XPath node selection:
var doc = XDocument.Load("file path here");
var slideElements = doc.XPathSelectElements("root/slide/*");
var values = string.Join(" ", slideElements.Select(element => element.Value));

Categories

Resources