Does XmlDocument.LoadXml append or replace? - c#

In c#, if I have this
doc = new XmlDocument();
doc.LoadXml("<.....>");
doc.LoadXml("<.....>");
Does that 2nd one do a replace or append to the doc object?

It replaces. This is pretty obvious if you think about it and consider that valid XML documents must have a single root node.
More importantly, use XDocument, it is just better.
using System.Xml.Linq;
...
var document = XDocument.Parse(...

Related

Find and replace text inside xml document using regular expression

I am using c# console app to get xml document. Now once xmldocument is loaded i want to search for specific href tag:
href="/abc/def
inside the xml document.
once that node is found i want to strip tag completly and just show Hello.
Hello
I think i can simply get the tag using regex. But can anyone please tell me how can i remove the href tag completly using regex?
xml & html same difference: tagged content. xml is stricter in it's formatting.
for this use case I would use transformations and xpath queries rebuild the document. As #Yahia stated, regex on tagged documents is typically a bad idea. the regex for parsing is far to complex to be affective as a generic solution.
The most popular technology for similar tasks is called XPath. (It is also a key component of XQuery and XSLT.) Would the following perhaps solve your task, too?
root.SelectSingleNode("//a[#href='/abc/def']").InnerText = "Hello";
You could try
string x = #"<?xml version='1.0'?>
<EXAMPLE>
<a href='/abc/def'>Hello</a>
</EXAMPLE>";
System.Xml.XmlDocument doc = new XmlDocument();
doc.LoadXml(x);
XmlNode n = doc.SelectSingleNode("//a[#href='/abc/def']");
XmlNode p = n.ParentNode;
p.RemoveChild(n);
System.Xml.XmlNode newNode = doc.CreateNode("element", "a", "");
newNode.InnerXml = "Hello";
p.AppendChild(newNode);
Not really sure if this is what you are trying to do but it should be enough to get you headed in right direction.

Append xml document to bottom of existing xml doc

I have an xml document and want to append another xml at the bottom of it. Using the xml classes in .NET, what is the quickest way to do this (in 3.5)?
Thanks
Quickest as in most efficient, or quickest as in simplest? For example:
XDocument doc1 = XDocument.Load(...);
XDocument doc2 = XDocument.Load(...);
// Copy the root element of doc2 to the end of doc1
doc1.Root.Add(doc2.Root);
doc1.Save(...);
Alternatively, you may want:
// Copy the *contents* of the root element of doc2 to the end of doc1
doc1.Root.Add(doc2.Root.Descendants());
If you can be more precise about your requirements, we may be able to help more. Note that an XML document can only have one root element, so you can't just put one document after another.
I doubt that you will be able to do this using the XML classes. XML libraries typically aim to protect you from creating poorly-formed XML, and the concatenation of two XML documents will be poorly formed because the document node will have two child elements.
If the .Net libraries do allow you to do this, I suggest you raise it as a bug.
var xml = new XmlDocument();
xml.AppendChild(...);
xml.PrependChild(...);
If you really want to add a second root node the fastest way would be to read the first file line by line and add it to the second file. That's a very dirty way and you'll get an invalid xml file!
System.IO.StreamWriter file1 = System.IO.File.AppendText(path);
System.IO.StreamReader file2 = new System.IO.StreamReader(path2)
while(!file2.EndOfStream)
{
file1.WriteLine(file2.ReadLine());
}
file1.Close();
file2.Close();
I even don't like this solution!

c# linq to xml

I have an xml string that I wish to traverse using LINQ to XML (I have never used this, so wish to learn). However when I try to use
XDocument xDoc = XDocument.Load(adminUsersXML);
var users = from result in xDoc.Descendants("Result")
select new
{
test = result.Element("USER_ID").Value
};
I get an error message saying illegal characters in path. reading up on it, it's because I cannot pass a standard string in this way. Is there a way to use XML LINQ qith a standard string?
Thanks.
My guess is that adminUsersXML is the XML itself rather than a path to a file containing XML. If that's the case, just use:
XDocument doc = XDocument.Parse(adminUsersXML);
As said in MSDN, you must use the Parse function to create a XDocument from a string.
I think adminUserXML is not a file but a string containing xml, which should be parsed to convert to XDocument with XDocument.Parse(adminUserXML)

Configuring XPath and use LINQ

i have a scenario where i need to check for the node count in a XML file. Since the XPath may vary for different scenarios, i would like to configure this in a xml / text file
I checked at XQuery but I hardly find any implementation in C#.
Since LINQ also does the similar thing, i am thinking of using it.
Ex. XML:
<ROOT><NODE1><TXT>ABC</TXT></NODE1><NODE1><TXT>DEF</TXT></NODE1></ROOT>
I would like to configure my condition like this (in a text file):
/ROOT/NODE1/TXT [COUNT=2]
there will n-number of xpath like this
How easily can I use LINQ, Check for XPATH and get the count?
Thanks in advance
Cheers,
Karthik
Check the reference System.Xml.Xpath which allows you to use xpath to work with Xml data.
XDocument doc = XDocument.Load(filePath);
var xPath = #"/ROOT/NODE1/TXT";
int count = doc.XPathSelectElements(xPath).Count();
XDocument doc = XDocument.Load(xmlFilePath);
int count = doc.Descendants("TXT").Count();
In this case you can do:
XDocument doc = XDocument.Load(filePath);
var xPath = #"/ROOT/NODE1/TXT";
int count = doc.Descendants(xPath.Substring(xPath.LastIndexOf("//") + 1)).Count();
but it's not general case, whould you explain more details about your condition to force using XPath strings?

Efficient way to construct an XML document from a string containing well formed XML for navigation?

I have a string that contains well formed xml in it. I want to navigate the XML in that string to extract the text in certain nodes. How do I efficiently accomplish this using a built-in .NET class. Which .NET XML class would you use and why?
Many thanks for your help.
Note 1: Linq is not available to me.
Note 2: Editing the XML is not important. Read-only access is what I need.
For speed, use an XmlReader:
using (StringReader sr = new StringReader(myString))
using (XmlReader xr = XmlReader.Create(sr))
{
while (xr.Read())
{
if (xr.NodeType == XmlNodeType.Element && xr.Name == "foo")
{
Console.WriteLine(xr.ReadString());
}
}
}
The above prints out the text content of every element named "foo" in the XML document. (Well, sort of. ReadString doesn't handle nested elements very gracefully.)
Using an XPathDocument is slower, because the entire document gets parsed before you can start searching it, but it has the merit of simplicity:
using (StringReader sr = new StringReader(myString))
{
XPathDocument d = new XPathDocument(sr);
foreach (XPathNavigator n in d.CreateNavigator().Select("//foo/text()"))
{
Console.WriteLine(n.Value);
}
}
If you're not concerned with performance or memory utilization, it's simplest to use an XmlDocument:
XmlDocument d = new XmlDocument();
d.LoadXml(myString);
foreach (XmlNode n in d.SelectNodes("//foo/text()"))
{
Console.WriteLine(n.Value);
}
For navigation? Probably XPathDocument:
string s = #"<xml/>";
XPathDocument doc = new XPathDocument(new StringReader(s));
From MSDN,
Provides a fast, read-only, in-memory representation of an XML document by using the XPath data model.
Unlike XmlDocument etc, it is optimised for readonly usage; more efficient but less powerful (i.e. you can't edit it). For notes on how to query it, see here.
I would use XmlDocument.Load() to get a DOM from the string. Then you can traverse it using the appropriate DOM methods or XPATH as needed.
It depends on the structure of XML. If it is relatively simple, then the most efficient way to wrap the string into StringReader, and then wrap that into XmlReader. The benefit is that you won't have to create an XML tree in memory, copying data from the string - you'll just read nodes one by one.
If the document structure is complicated enough, you might need (or want) a DOM - in which case XDocument.Parse should do the trick.

Categories