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.
Related
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>
Currently I have a working C# program that works as follows:
Accept .xls template with values (xls is manually created by user)
Save the values (matching fields) to the database
Convert and write .xls to XML. Please see below sample output:
Existing XML Structure
Now, what I want to do is:
Read the existing xml (the created xml)
Insert another set of nodes and subnodes (ReleaseLine and sub nodes). It must accept multiple ReleaseLine.
Save/create the new xml with appended nodes. Please see below output:
This is what I'm looking for:
My existing C# program is simple but the XML nodes and hierarchy is bloody deep. I just created the C# code using new XElement method and passing values for each nodes. Then I simply use xmlDocument.Save() method to write the xml.
[Existing XML Program][3]
To add nodes or append content in existing xml-data I´d use Linq to XML.
XElement xml = XElement.Load("file.xml");
xml.Add( new XElement("uberNode",
new XElement("childNode", content),
new XElement("anotherChildNode", content)));
xml.Save("file.xml");
Here are some other related solutions.
Add to specific node (with example):
Following exisiting XML-data:
`<Names>
<Name>
<prename>John</prename>
<lastname>Snow</lastname>
</Name>
<Name>
<prename>Harry</prename>
<lastname>Harry</lastname>
</Name>
</Names>`
Now I want to add an "age"-tag before the first "prename"-tag and a "family"-tag after the first "lastname"-tag.
XElement xml = XElement.Load("file.xml");
var childrens = xml.DescendantsAndSelf().ToArray();
var first_prename = childrens[2];
var first_lastname = childrens[3];
Console.WriteLine(childrens[0]); //prints out the whole content
first_prename.AddBeforeSelf(new XElement("age", 22));
first_lastname.AddAfterSelf(new XElement("family", new XElement("mother", "paula"), new XElement("father", "paul")));
xml.Save("file.xml");
Outcome:
`<Names>
<Name>
<age>22</age>
<prename>John</prename>
<lastname>Snow</lastname>
<family>
<mother>paula</mother>
<father>paul</father>
</family>
</Name>
<Name>
<prename>Harry</prename>
<lastname>Harry</lastname>
</Name>
</Names>`
I was facing the problem and Linq gave me the easiest way to accomplish that!
There are also other similar way e.g. here. But I tried a bit more and DescendantsAndSelf() made it easier for me to go through.
I found an answer to my question, here is the link http://www.xmlplease.com/add-xml-linq
Using XPathSelectElement method, I was able to find the right node and appended new block of XElement.
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.
<feed>
<entry>
<data>1234</data>
<content>Stackoverflow</content>
</entry>
</feed>
Next data..
I have to create above xml using xpath in c# is this possible to do..
I had done xml file using below code
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\Log_Data.xml");
XmlElement newelement = xmlDoc.CreateElement("entry");
XmlElement xmldata = xmlDoc.CreateElement("data");
XmlElement xmlcontent = xmlDoc.CreateElement("content");
xmldata.InnerText ="1234" ;
xmlcontent.InnerText ="Stackoverflow";
newelement.AppendChild(xmldata);
newelement.AppendChild(xmlcontent);
xmlDoc.DocumentElement.AppendChild(newelement);
xmlDoc.Save(#"C:\Log_Data.xml");
but i have to use Xpath like we do in sql to write queries like
"Insert into table............."
should it possible in .Net 2.0
XPath is a query language for XML documents. As such, it doesn't provide the capability to alter (delete or insert nodes) an XML document.
One of the most appropriate ways to create or alter an XML document (called XML transformation) is to use XSLT -- a language especially designed for XML transformations.
From C# one can use the .NET XslCompiledTransform class to perform any XSLT 1.0 transformation.
Third party .NET implementations exist for XSLT 2.0.
You have to create your own XPath parser to achieve this. Simple implementation of that can be found here.
Greeting,
What is the best practice to read all attributes from a child elements by ID attributes using C# in xml file listed down.
Thank you,
<?xml version="1.0" encoding="utf-8"?>
<WinDLN>
<Program ID="1" Name="CIS562" StartDate="9/8/2010 5:50:00 PM" EndDate="9/8/2010 9:15:00 PM" />
<Program ID="2" Name="CIS532" StartDate="10/8/2010 5:50:00 PM" EndDate="10/8/2010 9:15:00 PM" />
<Program ID="3" Name="ECE552" StartDate="6/8/2010 5:50:00 PM" EndDate="6/8/2010 9:15:00 PM" />
</WinDLN>
The following LINQ call should do the trick:
var attrs =
doc.Descendants("Program").First(prog =>
prog.Attribute("ID").Value == "2").Attributes();
The Descendants method gives you all elements (anywhere) in the XML document that are named "Program". Using First, you can get the first one that matches some specified predicate (e.g. has "ID" equal to "2"). Note that you can use FirstOrDefault if you want to get null when there is no such element. Finally, Attributes gives you a collection of all attribtues of the element.
I think that using LINQ to XML if you can is preferrable - you'll write the same code when working with XML or other data sources, so reading and writing the code is easy (once you learn LINQ).
There are many ways to do it, e.g. LINQ over XML. But using Xpath is definitely not dead yet:
class Program
{
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
string xml = #"... your xml ";
doc.LoadXml(xml);
// Using SelectNodes with Xpath
XmlNodeList list = doc.SelectNodes("WinDLN/Program[#ID='2']");
Console.WriteLine(list.Count); // prints 1
list = doc.SelectNodes("WinDLN/Program[#ID]");
Console.WriteLine(list.Count); // prints 3 (selected all IDs)
}
}
What method you'll choose is most often a matter of taste, select the API you're most comfortable with.