XmlDocument get sub items - c#

i'm trying to get the sub item from this XML document:
XML CODE HERE :
<RUNNABLES>
<RUNNABLE-ENTITY UUID="1661dcae-c4b9-4f47-8b68-cb99c677bdd6">
<SHORT-NAME>RCtApElg_mlm</SHORT-NAME>
<DESC>
<L-2 L="FOR-ALL">The unique runnable entity of the Main Lights SW Component</L-2>
</DESC>
</RUNNABLES>
So far, this is what i made:
C# code here
XmlDocument xmlReader = new XmlDocument();
xmlReader.PreserveWhitespace = false;
xmlReader.Load(strfilename);
XmlNodeList elemList = xmlReader.SelectNodes("/RUNNABLES/RUNNABLE-ENTITY/SHORT-NAME");
How I can specify to read SHORT-NAME tag and get "RCtApElg_mlm" value as result?

Provided you fix the sample xml (it misses the closure tag for RUNNABLE-ENTITY), this should work:
XmlDocument xmlReader = new XmlDocument();
xmlReader.PreserveWhitespace = false;
xmlReader.Load(strfilename);
XmlNodeList elemList = xmlReader.SelectNodes("//RUNNABLES/RUNNABLE-ENTITY/SHORT-NAME");
string value = elemList.Item(0).InnerText;

I think you need to use:
.Value
XmlNodeList elemList = xmlReader.SelectNodes("/RUNNABLES/RUNNABLE-ENTITY/SHORT-NAME").Value;

Well this is what I did:
XmlNode node = xmlReader.DocumentElement.FirstChild;
XmlNodeList lstPackage = node.ChildNodes;
for (int i = 0; i < 2; i++)
{
//MessageBox.Show(lstPackage[i].Name.ToString());
if (lstPackage[i].Name == "AR-PACKAGE")
{
aux++;
}
if(aux==2)
{
aux = 0;
XmlNodeList lstShortname = lstPackage[i].FirstChild.ChildNodes;
// Display the value of its first child node
for (int j = 0; j < lstShortname.Count; j++)
MessageBox.Show(lstShortname[j].InnerText);
}
}
Dont know if its the best option, but I get as result.
Thanks!

Related

how to append node to a specific place in xml file

I have an XML file like this, in it there is more than one table and I am trying to add a new node at the end of a specific table in the xml file. The user will choose the table and enter his data into a DataGridView.
<?xml version="1.0" encoding="UTF-8"?>
<table name="emloyees">
<emloyees>
<emp_num>employee 1</emp_num>
<department>sales</department>
<salary>1000</salary>
</employees>
<employees>
<emp_num>employee 2</emp_num>
<department>IT</department>
<salary>2000</salary>
</employees>
((for example I want to add new employees node here))
<table name="projects">
<projects>
<proj_num>project 1</proj_num>
<name>hosbital system</name>
<num_mempers>5 members</num_mempers>
</projects>
<projects>
<proj_num>project 2</proj_num>
<name>library system</name>
<num_mempers>4 members</num_mempers>
</projects>
</table>
</table>
I wrote this code, but instead of inserting a new node, the last node of the table gets replaced with the new node instead. How do I fix this?
private void button4_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("Data.xml");
string tablename = comboBox1.SelectedItem.ToString();
XmlNodeList row = doc.GetElementsByTagName(tablename);
int c = row.Count;
for (int j = 0; j < dataGridView1.Rows.Count - 1; j++)
{
XmlNodeList child = row[c - 1].ChildNodes;
XmlElement element = doc.CreateElement(tablename);
for (int k = 0; k < child.Count; k++)
{
XmlElement node = doc.CreateElement(child[k].ToString());
child[k].InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString();
element.AppendChild(node);
}
XmlElement root = doc.DocumentElement;
root.AppendChild(element);
doc.Save("Data.xml");
}
dataGridView1.Rows.Clear();
MessageBox.Show("Successfully Added !!");
}
It seems the problem is here.
for (int k = 0; k < child.Count; k++)
{
XmlElement node = doc.CreateElement(child[k].ToString());
child[k].InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString(); // < here
element.AppendChild(node);
}
You are setting the child[k]'s inner text, not the value of the node you created.
Change child[k] to node
node.InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString();
Your title asks to place the node at a specific place, but your code isn't doing it. You'll need to use the parentNode.InsertAfter(newNode, refNode) method.
So instead of root.AppendChild(element);. Which puts the node at the bottom of the file, use root.InsertAfter(element, child[child.Count - 1]) to put the new node after the last child type you are setting.
AppendChild MSDN docs.

How Do I Solve Object Reference Not Set To An Instance Of An Object

Am trying to loop through xmlnodes. but getting this error "Object reference not set to an instance of an object." My main goal was to loop it through the datgridviewcell but i don't know how i can take it further. I know the column indexes for font,date and comment from my grid. how can i loop through those column indexes and be able to parse the value to string?
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="Button"xml:space="preserve">
<value></value>
<comment>[Font][/Font][DateStamp][/DateStamp[Comment][/Comment]</comment>
</data>
XmlNodeList _Nodelist = _doc.SelectNodes("/root");
foreach(XmlNode _Xnode in _Nodelist)
{
XmlNode _data = _Xnode.SelectSingleNode("data");
XmlNodeList _CommentNodes = _data.SelectNodes("comment");
if(_CommentNodes != null)
{
foreach(XmlNode node in _CommentNodes)
{
XmlNode _comment = node.SelectSingleNode("comment");
{
string _font = _comment["Font"].InnerText; //it throws the error here
string _Date = _comment["DateStamp"].InnerText;
string _Comment = _comment["Comment"].InnerText;
}
}
}
}
Your problems are that
There is only one level of <comment> node, but you are looking for nested comment nodes.
The text inside the <comment> node isn't XML - it's just text content. Thus it cannot be parsed as if it contained child XML elements.
Instead you need to do something like the following:
XmlNodeList _Nodelist = _doc.SelectNodes("/root");
foreach (XmlNode root in _Nodelist)
{
XmlNode _data = root.SelectSingleNode("data");
if (_data == null)
continue;
XmlNodeList _CommentNodes = _data.SelectNodes("comment");
foreach (XmlNode _comment in _CommentNodes)
{
var text = _comment.InnerText;
// text = "[Font][/Font][DateStamp][/DateStamp[Comment][/Comment]"
string _font = text.Between("[Font]", "[/Font]", StringComparison.Ordinal);
string _Date = text.Between("[DateStamp]", "[/DateStamp]", StringComparison.Ordinal);
string _Comment = text.Between("[Comment]", "[/Comment]", StringComparison.Ordinal);
}
}
Using the extension method:
public static class TextHelper
{
public static string Between(this string input, string start, string end, StringComparison comparison)
{
var startIndex = input.IndexOf(start, comparison);
if (startIndex < 0)
return null;
startIndex += start.Length;
var endIndex = input.IndexOf(end, startIndex, comparison);
if (endIndex < 0)
return null;
return input.Substring(startIndex, endIndex - startIndex);
}
}
Note that _Date will be null because, as #colmde noted, "[/DateStamp" is missing a closing bracket.

Reading value of an XML node

i need to get the value of an Node in an XML File.
My XML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<PRODUCTS>
<IPHONE>
<NAME>iPhone 5s</NAME>
<MODEL>5s</MODEL>
<PRICE>899</PRICE>
<COLOR>Gold</COLOR>
</IPHONE>
I want to get the text (iPhone 5s) from the file.
I have tried several things I have found on the internet:
protected void Page_Load(object sender, EventArgs e)
{
String[][] products = new String[3][];
int i = 0;
int j = 0;
System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader("../XML-Test/Webshop-products.xml");
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.LocalName.Equals("NAME"))
{
//Name of product
products[i][j] = reader.ReadInnerXml();
j++;
}
if (reader.LocalName.Equals("MODEL"))
{
//Model
products[i][j] = reader.ReadString();
j++;
}
if (reader.LocalName.Equals("PRICE"))
{
//Price
products[i][j] = reader.Value;
j++;
}
if (reader.LocalName.Equals("COLOR"))
{
//Color
products[i][j] = reader.Value;
j++;
i++;
}
}
}
for (int k = 0; k < products.Length; k++)
{
for (int l = 0; l < products[k].Length; l++)
{
Console.Write(products[k][l]);
}
}
}
No method seems to work. When i run the project (ASP.NET Project) i get the following error:
System.NullReferenceException: Object reference not set to an instance to an object
How can i get the values of the nodes?
You can use Linq To Xml.
Assuming you you have other products like IPHONE under PRODUCTS
var products = XDocument.Load(filename).Root
.Elements()
.Select(x => new
{
Product = x.Name.LocalName,
Name = (string)x.Element("NAME"),
Model = (string)x.Element("MODEL"),
Price = (decimal)x.Element("PRICE"),
Color = (string)x.Element("COLOR")
})
.ToList();
I suggest to use Linq to Xml:
var xdoc = XDocument.Load("../XML-Test/Webshop-products.xml");
var p = xdoc.Root.Element("IPHONE"); // get first IPHONE from file
if (iPhoneElement == null)
return; // handle case when there is no IPHONE in xml file
var iPhone = new {
Name = (string)p.Element("NAME"),
Model = (string)p.Element("MODEL"),
Price = (decimal)p.Element("PRICE"),
Color = (string)p.Element("COLOR")
};
Then you can use name, model, price or color of iPhone object. E.g.
iPhone.Name
Note - if there is many iPhones in file, you can grab them all:
var iPhones = from p in xdoc.Root.Elements("IPHONE")
select new {
Name = (string)p.Element("NAME"),
Model = (string)p.Element("MODEL"),
Price = (decimal)p.Element("PRICE"),
Color = (string)p.Element("COLOR")
};
You may also want to have a look at the methods given below.
1) XmlDocument and XmlNode
2) Serialization and Deserialization.
3) Simplified example of Serialization and Deserialization

How to add a child of a child?

I'm a beginner in C# and have a simple question about TreeView.
I want to do something like this:
> -Root
> -child1
> -child2
> -child3
> -....
I have this:
child.Text = des[j];
root.Nodes.Add(child);
But it just yields something like this:
> -Root
> -child1
I want:
To have a child of a child.
To create 10 TreeNodes in a for statement.
With different names like: root1, root2, root3, etc.
for (i = 0; i < 10; i++)
{
TreeNode root = new TreeNode();
}
You need to add the TreeNode to the Nodes collection of the child, not the root.
child.Text = des[j];
root.Nodes.Add(child);
TreeNode NextChild = new TreeNode();
NextChild.Text = "something";
child.Nodes.Add(NextChild);
For your second Question, you would need to store those treenodes in some kind of datastructure. If you want to name each one, a hashtable would be a good bet.
Hashtable myHT = new Hashtable();
for (int i = 0; i < 10; i++)
{
TreeNode root = new TreeNode();
myHT.Add("Root" + i, root);
}
You would then access them like,
TreeNode myRoot = (TreeNode)myHT["Root1"];
If you are comfortable with Generics you can use the System.Collections.Generic.Dictionary instead for a generic version.
You only need to keep track of the current node and the child to be inserted.
At i = 0, the current node value is the root node.
At i > 0, the current node value is the last child node inserted.
Then, you can try something like this...
TreeNode current = new TreeNode(); // Root node.
current.Text = string.Format("Root");
for (int i = 0; i < 10; i++)
{
TreeNode child = new TreeNode();
child.Text = string.Format("Child: {0}", i);
current.Nodes.Add(child);
current = child;
}
The result of this code will be:
Root
Child: 0
Child: 1
Child: 2

Remove XML Nodes as per user input

I am trying to write all the dropped elements prperties in a xml document to save in the database.When the user delete a dropped element ,i need to remove that element from the Xml doc.
XmlDocument oXmlDocument = new XmlDocument();
oXmlDocument.Load(#"D:\VanithaApps\SenMail\DiagramData.xml");
Boolean nodeExits = false;
XmlNode oXmlRootNode = oXmlDocument.SelectSingleNode("records");
XmlNodeList xmlnode = oXmlDocument.GetElementsByTagName("record");
if (delete=="1")
{
if (xmlnode.Count > 0)
{
for (int i = 0; i < xmlnode.Count; i++)
{
string tempVar = element.Substring(0, element.Length - 1);
if (xmlnode[i].ChildNodes[2].InnerText == tempVar)
{
try
{
oXmlRootNode.RemoveChild(xmlnode[i]);
goto Found;
}
catch(Exception ex)
{
ex.ToString();
}
}
}
}
}
if (xmlnode.Count > 0)
{
for (int i = 0; i < xmlnode.Count; i++)
{
string tempVar = element.Substring(0, element.Length-1);
if (xmlnode[i].ChildNodes[2].InnerText == tempVar)
{
nodeExits = true;
XmlNode XAxis = xmlnode[i].ChildNodes[0];
XAxis.InnerText = Convert.ToString(x);
XmlNode YAxis = xmlnode[i].ChildNodes[1];
YAxis.InnerText = Convert.ToString(y);
}
}
if (nodeExits == false)
{
CreateNewNode(x, y, element, userid, oXmlDocument, oXmlRootNode);
}
}
else
{
CreateNewNode(x, y, element, userid, oXmlDocument, oXmlRootNode);
}
Found:
int result = 0;
return result;
I haven't used xml extensively before
<?xml version="1.0" encoding="utf-8"?>
<records>
<record>
<X-Cordinate>774</X-Cordinate>
<Y-Cordinate>173</Y-Cordinate>
<Element>drag595</Element>
<UserID>1</UserID>
</record>
</records>
i want to delete whose child 'Element' value is equal to tempVar.Here if the Element value is equal to drag595 ,i want to remove that entry from my XML .
Change
oXmlRootNode.RemoveChild(xmlnode[i]);//not working//
to
xmlnode[i].ParentNode.RemoveChild(xmlnode[i]);
Children can only be removed from their respective parents.

Categories

Resources