How to Replace Parent Property of XElement value with New XElement value? - c#

I'm using XElement class and Selecting particular XML Element. I want to Replace the Parent property of XElement xml content with another new XElement xml content.Is there any way to replace the parent xml element with another new.
Example
1.Loding XML 1 document
2.Getting catalog xml elements
XElement old = document.XPathSelectElement(#"cd/catalog");
To replace - getting value from loading XML 2
XElement toreplace = documentReplace.XPathSelectElement(#"cd/first/catalog");
Replacing
old.Parent.ReplaceWith(toreplace)
Here, I'm trying to Replace the old parent property value with XElement toreplace value but parent property is not replacing
XML 1
<cd>
<catalog>
<a>parent</a>
<b>catalog</b>
</catalog>
</cd>
XML 2
<cd>
<first>
<catalog>
<a>first</a>
<b>catalog</b>
</catalog>
</first>
</cd>
O/P wanted
XML 1
<cd>
<catalog>
<a>first</a>
<b>catalog</b>
</catalog>
</cd>

Related

Concatenate XML fields in one single record

I am new to working with XML in C#. I have a requirement to concatenate multiple fields in one single record.
For example I have an XML with multiple Records:
Input
<Students>---------------------->1st Record
<Validate>True</Validate>
<StudentName>Joe</StudentName>
<ID>1</ID>
<BookName>C#</BookName>
</Students>
<Students>----------------------->2nd Record
<StudentName>Van</StudentName>
<ID>2</ID>
<BookName>Java</BookName>
</Students>
The field <validate> will occur only once and the expected Output is that the 2nd Record under students i.e StudentName, ID, BookName should come under the 1st Record <Students> tag
OutPut
<Students>------------------->Both record should be added to one Record
<Validate>True</Validate>
<StudentName>Joe</StudentName>
<ID>1</ID>
<BookName>C#</BookName>
<StudentName>Van</StudentName>
<ID>2</ID>
<BookName>Java</BookName>
</Students>
The easiest way is to use LINQ to XML. You parse the XML, get all the child elements in each Students element and put them into a a single new Students element:
var doc = XDocument.Parse(xml);
var children = doc.Descendants("Students")
.Elements();
var newStudents = new XElement("Students", children);
See this fiddle for a working example.

combine two xml_docs C# xmlDocument

I have been using the following SO, How to merge two XmlDocuments in C#, to try and merge two sample xml files into one. Essentially here are my two xml files
test1.xml:
<root>
<Name>
<id>4</id>
<First_name>Tony</First_name>
<last_name>""</last_name>
</Name>
<Name>
<id>6</id>
<First_name>Donny</First_name>
<last_name>Test</last_name>
<middle_name>Ward</middle_name>
</Name>
</root>
And test2.xml
<root>
<Name>
<id>1</id>
<First_name>Nick</First_name>
<last_name>Tester</last_name>
</Name>
<Name>
<id>2</id>
<First_name>Lauren</First_name>
<last_name>MsTester</last_name>
</Name>
</root>
I am using this code snippet it to merge the into the one file but the procedure is not actually combining them. I am a little knew to xmlDocument class and still trying to navigate this issue correctly.
Code:
XmlDocument xmlreader1 = new XmlDocument();
xmlreader1.Load("C:\\Temp\\test1.xml");
XmlDocument xmlreader2 = new XmlDocument();
xmlreader2.Load("C:\\Temp\\test2.xml");
foreach (XmlNode node in xmlreader2.DocumentElement.ChildNodes)
{
XmlNode importedDocument = xmlreader1.ImportNode(node, true);
xmlreader1.DocumentElement.AppendChild(importedDocument);
}
I believe this is correct to take each child node of root (in this case <name>) from test2.xml and append it to test1.xml. I have also tried as:
XmlNode importedDocument = xmlreader1.ImportNode(xmlreader2.DocumentElement, true);
xmlreader1.DocumentElement.AppendChild(importedDocument);
to no avail again any suggestions would be greatly appreciated.
It's not entirely clear what merge operations you need to perform - but if you just need to copy the root node's child elements, that's really simple with LINQ to XML:
XDocument doc1 = XDocument.Load("test1.xml");
XDocument doc2 = XDocument.Load("test2.xml");
doc1.Root.Add(doc2.Root.Elements());
doc1.Save("test3.xml");
This will not perform any actual merging though - if you have elements with the same ID in both files, you'll end up with both elements in the result, rather than one merged element.
Personally I always prefer using LINQ to XML over the old XmlDocument API - I would strongly recommend using it when you have the opportunity to do so.

XPath last() does not work properly

I have following xml
<root>
<data>
<person>tewst</person>
<data>
<phone>djk</phone>
<email>dsd</email>
</data>
</data>
</root>
Using c# SelectSingleNode I am trying to get to second "data" node and insert the new element call "phone2" after email tag.
Issue is I can not get to the correct "data" node. This is the code I am using to get there and it does not work. Any help would be appreciated. Thank you
XMLDocument doc = new XMLDocument("xml file here");
var node = doc.SelectSingleNode("//data[last()]");
XMLElement phone1 = doc.CreateElement("phone2");
phone1.InnerText = "12";
node.AppendChild(phone1);
Problem is that node is null.
Solution:
XMLDocument doc = new XMLDocument("xml file here");
var node = doc.SelectSingleNode("(//data)[last()]");
//data[last()] selects data nodes that are their parent's last data child, so it selects 2 nodes in your example:
1) last data child of the root node
<data>
<person>tewst</person>
<data>
<phone>djk</phone>
<email>dsd</email>
</data>
</data>
2) and last data child of the first data node
<data>
<phone>djk</phone>
<email>dsd</email>
</data>
To select the last data in the whole document, use:
(//data)[last()]
//data will generate the node-set for all descendant data elements, nested or not,
[last()] will select the last node of the node-set
with the brackets () around //data, it ensures it's interpreted as //data then [last()], instead of // then data[last()]
There are a couple different ways you can do this.
(1) If you know that the structure of the XML will always be like the above - "root" element, exactly one "data" child, and exactly one "data" child beneath the "data" parent, you can access the second "data" element directly using the XPath expression:
XmlNode node = doc.SelectSingleNode("/root/data/data");
(2) If there are multiple "data" elements beneath the "root" element, then you can do the following:
XmlNodeList nodeList = doc.SelectNodes("//data/data");
This XPath expresion will return the first "data" element beneath every top level "data" element in the document. So for instance, if you had an XML document like this:
<root>
<data>
<person>tewst</person>
<data>
<phone>djk</phone>
<email>dsd</email>
</data>
</data>
<data>
<person>two</person>
<data>
<phone>bbb</phone>
<email>ddd</email>
</data>
</data>
</root>
... the output of this code snipped:
XmlNodeList nodeList = doc.SelectNodes("//data/data");
foreach (XmlNode parentData in nodeList)
Console.WriteLine(parentData.InnerXml.ToString());
... will produce:
<phone>djk</phone><email>dsd</email>
<phone>bbb</phone><email>ddd</email>
Hope this helps.

c# xmlnode select single node to remove

I have an XML document that has nodes/values like this:
<data name="btnAutoTrans" xml:space="preserve">
<value>Auto Trans</value>
</data>
<data name="btnDieEngine" xml:space="preserve">
<value>Diesel Engine</value>
</data>
I need to select a single node for a specific name="btnDieEngine" (for example)
but all the code I have tried from searching google always returns NULL value.
The original code I had was
XmlNode node = xmldoc.SelectSingleNode("data[name='btnDieEngine']");
but this returns null.
Any help would be appreciated
Your XPath is invalid. Try that one:
XmlNode node = xmldoc.SelectSingleNode("data[#name='btnDieEngine']");

How to remove an element from XML file using Linq to XML and lambda expression

I have an xml as below
<Person>
<Name>xxx</Name>
<Age>xx</Age>
<Data>xxxx</Data>
</Person>
<Person>
<Name>xxx</Name>
<Age>xx</Age>
<Data>xxxx</Data>
</Person>
<Person>
<Name>xxx</Name>
<Age>xx</Age>
<Data>xxxx</Data>
</Person>
How to remove <Data> element from the tree using Linq to XML, Lamda Expression in C#? where <Data> is a auto generated element and XML structure may vary.
it all depends on what element you want to remove but you can use something like this
XDocument people = XDocument.Load("filenamre.xml");
IEnumerable<XElement> Person = people.Element("Person");
//gets the element you want to remove based on value
XElement name = Person.Where(p => p.Element("xxx").Value == "1").FirstOrDefault();
//removes the name
name.Remove();
//create a new file without the element
people.Save(Server.MapPath("Newfilenamre.xml"));
Removing element other than first one. Means only first must be there rest all must be deleted.

Categories