How to create a path to xml element in C# - c#

I want to create a routing(path) to xml element and assign it to a variable so i can access it
fast in the future.
The element, which is a child of other elements, can change its position in the document
so i cant use methods like first child or indexing that rely on position.
The path to the element will always stay constant and there is no other path like it.
If we look at a short example so i want a path to level4 value(header4) so i can modify it.
<level1>
<level2>
<level3>header3</level3>
<level4>header4</level4>
<level3>header31</level31>
</level2>
<level2>
<level3>nnn</level3>
<level3>nnnnn</level31>
</level2>
</level1>

You've got to use XPath in that case.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Path of the xml");
XmlNode titleNode = xmlDoc.SelectSingleNode("//level1/level2/level3");

You can use XPath for this.
XmlDocument doc; // assuming the xml is already in doc
XmlNode node = doc.SelectSingleNode("/level1/level2/level3/level4");
if(node != null)
{
node.InnerText = "New value";
}
If there could be more than one level4 then you could do this:
XmlDocument doc; // assuming the xml is already in doc
XmlNodeList nodes = doc.SelectNodes("/level1/level2/level3/level4");
if(nodes != null)
{
foreach(XmlNode node in nodes)
{
node.InnerText = "New value";
}
}

Related

Adding a node in the beginning of XML parent node

I wanted to add a xmlNode in a parent but at the top/beginning. Is there a variant of XMLNode.AppendChild() that i can use?
As far as I understand your question you are probably looking for the XmlNode.PrependChild() method.
Example:
XmlDocument doc = new XmlDocument();
XmlNode root = doc.DocumentElement;
//Create a new node.
XmlElement node = doc.CreateElement("price");
//Add the node to the document.
root.PrependChild(node);
MSDN documentation
I believe the question is asking how to add a node to the beginning of the XML file. I did that in the following manner:
// This is the main xml document
XmlDocument document = new XmlDocument();
// This part is creation of RootNode, however you want
XmlNode RootNode = document.CreateElement("Comments");
document.AppendChild(RootNode);
//Adding first child node as usual
XmlNode CommentNode1 = document.CreateElement("UserComment");
RootNode.AppendChild(commentNode1);
//Now create a child node and add it to the beginning of the XML file
XmlNode CommentNode2 = document.CreateElement("UserComment");
RootNode.InsertBefore(commentNode2, RootNode.FirstChild);

Xpath selection of all attributes

I have the xml below in a c# class.
string xml =#"<?xml version='1.0' encoding='UTF-8'?>
<call method='importCube'>
<credentials login='sampleuser#company.com' password='my_pwd' instanceCode='INSTANCE1'/>
<importDataOptions version='Plan' allowParallel='false' moveBPtr='false'/>
I need to update the XML held within the node attributes i.e.
string xml =#"<?xml version='1.0' encoding='UTF-8'?>
<call method='importCube'>
<credentials login='testuser#test.com' password='userpassword' instanceCode='userinstance'/>
<importDataOptions version='Actual' allowParallel='true' moveBPtr='true'/>
I've written code to do this :
// instantiate XmlDocument and load XML from string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
// get a list of nodes
XmlNodeList aNodes = doc.SelectNodes("/call/credentials");
// loop through all nodes
foreach (XmlNode aNode in aNodes)
{
// grab the attribute
XmlAttribute idLogin = aNode.Attributes["login"];
XmlAttribute idPass = aNode.Attributes["password"];
XmlAttribute idInstance = aNode.Attributes["instanceCode"];
idLogin.Value = "myemail.com";
idPass.Value = "passtest";
idInstance.Value = "TestInstance";
}
It works but the issue at the minute is that I have to repeat the whole code block for each node path i.e.
XmlNodeList aNodes = doc.SelectNodes("/call/importDataOptions");
....
There has to be a better way. Any ideas how I can rip through the attributes in 1 pass?
Maybe just using a cast to XmlElement could help you to reduce your code:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach (XmlElement credential in doc.SelectNodes("/call/credentials"))
{
credential.SetAttribute("login" , "myemail.com" );
credential.SetAttribute("password" , "passtest" );
credential.SetAttribute("instanceCode", "TestInstance");
}
Another option is to create an object structure which resembles your XML vocabulary and deserialize your input into that objects, but it seems overkill.
EDIT: Per your comment, you could go with:
foreach (XmlElement node in doc.SelectNodes("/call/*")) // it's case sensitive
{
switch(node.Name)
{
case "credentials":
node.SetAttribute("login" , "myemail.com" );
node.SetAttribute("password" , "passtest" );
node.SetAttribute("instanceCode", "TestInstance");
break;
case "importDataOptions":
// ...
break;
default:
throw new ArgumentOutOfRangeException("Unexpected node: "+node.Name);
}
}

inserting xml element into multiple nodes

I have the following XML
<ROOT>
<FSM338_Container>
<FSM338_Details>
<RunDate>2013-05-29 09:43:00</RunDate>
<Uic>21690</Uic>
<Date>2013-06-10 00:00:00</Date>
<CASHBREAK>199</CASHBREAK>
<CASHLUNCH>199</CASHLUNCH>
</FSM338_Details>
<FSM338_Details>
<RunDate>2013-05-29 09:43:00</RunDate>
<Uic>21690</Uic>
<Date>2013-06-10 00:00:00</Date>
<CASHBREAK>199</CASHBREAK>
<CASHLUNCH>199</CASHLUNCH>
</FSM338_Details>
</FSM338_Container>
<BillingReport>
<RunDate>2013-05-29 09:43:00</RunDate>
<Uic>21690</Uic>
<Date>2013-06-10 00:00:00</Date>
<gaindacd>1</gaindacd>
<docnum>07000F</docnum>
</BillingReport>
<DataElements>
<unitid>12345</unitid>
<fbocost>0.00</fbo>
</DataElements>
</ROOT>
I need to load the xml doc and add in several elements whenever I find the element named "Uic" . In short if I find "Uic" add in the element <someElement>my stuff here</someElement> at the same level as UIC at all locations.
I'Ve used
XmlDocument xDoc = new XmlDocument();
xDoc.Load(#"path_to_xml.xml");
list = xDoc.GetElementsByTagName("Uic");
I used insertBefore to add in my element but I can get it to copy to only the first element
You can use SelectNodes() method of XmlNode which accepts xpath expression.
XmlNodeList nodes = xDoc.DocumentElement.SelectNodes("Uic");
foreach(XmlNode node in nodes) {
XmlElement element = xDoc.CreateElement("SomeElement");
element.InnerText = "anything";
node.ParentNode.AppendChild(element);
}

how to check xmlnode for innertext or value in c#?

I created xmlnodelist and i want to handle the value of elements that dont have childs.
at the following code i'm checking for childnodes and i get true from all of the elements, even
those without childs.
how can i pick the last elements in the tree and handle the value's?
XmlDocument XDoc = new XmlDocument();
XDoc.Load("d://avi.xml");
XmlNodeList XList = XDoc.SelectNodes("//*");
foreach (XmlElement XNode in XList)
{
if (XNode.HasChildNodes == true)
{
Console.WriteLine("this node has childs");
continue;
}
else Console.WriteLine("this node dont have childs");
}
<level1>
<level2>
<level3>header3</level3>
<level4>another</level4>
<level31>header31</level31>
</level2>
<level2>
<level3>111</level3>
<level31>nn</level31>
</level2>
</level1>
How about using Linq to Xml for this?
var xElem = XElement.Parse(xml);
var leafElements = xElem.Descendants()
.Where(e => !e.HasElements)
.ToList();
The text within an element is a "node" as well. What you want is
if (XNode.ChildNodes.Any(n=>n.NodeType == XmlNodeType.Element))
Alternatively you can loop through the ChildNodes and see if one of them is an element.

How to add and delete an XML node?

I have this code below. I want to add a new node in it to hold more user records and if I want I can remove them. Can anyone help me?
string filename = "text.xml";
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("Login");
XmlElement id = doc.CreateElement("passWord");
root.SetAttribute("userName", nameTxb.Text);
id.SetAttribute("passWord", passwordTxb.Text);
XmlElement name = doc.CreateElement("UserName");
XmlElement passd = doc.CreateElement("PassWord");
name.InnerText = nameTxb.Text;
passd.InnerText = passwordTxb.Text;
root.AppendChild(name);
root.AppendChild(passd);
doc.AppendChild(root);
doc.Save(filename);
MessageBox.Show("Created SuccesFully!");
this.Close();
Your XML document is stored in variable doc. You may use doc.SelectNodes() to select specified nodes using XPATH. You may also iterate over selected nodes and append childs, remove childs etc.
var nodes = doc.SelectNodes("xpath");
foreach(XmlNode node in nodes)
{
//
}
This will remove an element. You can keep using SelectSingleNode() to move down through the branches of the xml. element can also be selected that way - for this example, just consider it an arbitrary starting point.
someElement.RemoveChild(oDoc.SelectSingleNode("Parent").SelectSingleNode("Child"));
As far as I know, you can also use the same method at the XmlDocument level too.
Hope this helps.

Categories