Writing in xml does not keep the formatting? - c#

I have this string :
<test>I am a test</test>
But when I write it in my xml file, and open it, I have this :
<test>I am a test</test>
I don't know how to use the good formatting. I tried HttpUtility.HtmlDecode, but it does not solve my problem.
Do you have an idea on this ?
Edit : Sorry for not having posted my code before, I thought my problem was really really trivial. Here is a sample I just wrote that resumes the situation (I'm not at work anymore so I don't have the original code) :
XmlDocument xmlDoc = new XmlDocument();
doc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
string content = xmlDoc.DocumentElement.FirstChild.InnerXml;
XDocument saveFile = new XDocument();
saveFile = new XDocument(new XElement("settings", content));
saveFile.Save("myFile.xml");
I just want my xml file content looks like my original string,
so in my case the file would normally contain :
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Right ? But instead, I have something like :
<settings><root><test>I am a test</test></root>
</settings>

You can do something along the lines of Converting XDocument to XmlDocument and vice versa to convert the root element of your XmlDocument to an XElement and then add it to your XDocument:
public static class XmlDocumentExtensions
{
public static XElement ToXElement(this XmlDocument xmlDocument)
{
if (xmlDocument == null)
throw new ArgumentNullException("xmlDocument");
if (xmlDocument.DocumentElement == null)
return null;
using (var nodeReader = new XmlNodeReader(xmlDocument.DocumentElement))
{
return XElement.Load(nodeReader);
}
}
}
And then use as follows:
// Get legacy XmlDocument
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
// Add its root element to the XDocument
XDocument saveFile = new XDocument(
new XElement("settings", xmlDoc.ToXElement()));
// Save
Debug.WriteLine(saveFile.ToString());
And the output is:
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Note this avoids the overhead of converting the XmlDocument to an XML string and re-parsing it from scratch.

Related

Using XDocument to read the root element from XML using C# is not showing the root element

I am new to C# programming and trying to update the XML file using C#. Here when I am trying to get the root element using XDocument it is showing the complete script in the file.
Below is my code explanation:
I am having the below function and it is reading the file path from the command line arguments.
private XDocument doc;
public void Update(string filepath)
{
string filename = Path.GetFileName(filepath);
doc = xDocument.Load(filepath);
XElement rootelement = doc.Root;
}
Into the filepath variable, we are taking the path "E:\BuilderTest\COMMON.wxs"
Then we are loading the file using XDocument.
But when we are trying to get the rootelement from the file, it is not showing the root element. Instead, it is showing the complete data in the file.
But when I am using XmlDocument() instead of XDocument() I am able to see only the root element.
Below is the code using XmlDocument():
private XmlDocument doc;
public void Update(string filepath)
{
string filename = Path.GetFileName(filepath);
doc = new XmlDocument();
doc.Load(filepath);
XmlElement rootelement = doc.DocumentElement;
}
Please help me by providing your valuable inputs on this.
XDocument and XmlDocument are different class structure to follow as per requirement.
XDocument will work like below
XDocument doc;
doc = XDocument.Load(filepath);
XElement root = doc.Root;
Root, Descendants, Elements are the operations provided in XDocument. For every node its gives XElement
In your case you should use doc.Root to find the element, then use .Value to get its value
XElement comes with System.Xml.Linq. It is derived from XNode.
It gives you serialized information of every node one by one.
On the other hand XMLDocument will work like below
XmlDocument doc;
doc = new XmlDocument();
doc.Load(filepath);
XmlElement rootelement = doc.DocumentElement;
XmlElement comes with System.Xml. It is derived from XmlNode which is again derived from IEnumerable.
It gives you information in a Enumerable which you can easily parse.

Select xml file part with xpath and xdocument - C#/Win8

I am building a Windows 8 app, and I need to extract the whole XML node and its children as string from a large xml document, and the method that does that so far looks like this:
public string GetNodeContent(string path)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.IgnoreComments = true;
using (XmlReader reader = XmlReader.Create("something.xml", settings))
{
reader.MoveToContent();
reader.Read();
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadOuterXml());
IXmlNode node = doc.SelectSingleNode(path);
return node.InnerText;
}
}
When I pass any form of xpath, node gets the value of null. I'm using the reader to get the first child of root node, and then use XMLDocument to create one from that xml. Since it's Windows 8, apparently, I can't use XPathSelectElements method and this is the only way I can't think of. Is there a way to do it using this, or any other logic?
Thank you in advance for your answers.
[UPDATE]
Let's say XML has this general form:
<nodeone attributes...>
<nodetwo attributes...>
<nodethree attributes... />
<nodethree attributes... />
<nodethree attributes... />
</nodetwo>
</nodeone >
I expect to get as a result nodetwo and all of its children in the form of xml string when i pass "/nodeone/nodetwo" or "//nodetwo"
I've come up with this solution, the whole approach was wrong to start with. The problematic part was the fact that this code
reader.MoveToContent();
reader.Read();
ignores the namespace by itself, because it skips the root tag. This is the new, working code:
public static async Task<string> ReadFileTest(string xpath)
{
StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync("NameOfFolderWithXML");
StorageFile xmlFile = await folder.GetFileAsync("filename.xml");
XmlDocument xmldoc = await XmlDocument.LoadFromFileAsync(xmlFile);
var nodes = doc.SelectNodes(xpath);
XmlElement element = (XmlElement)nodes[0];
return element.GetXml();
}

Preserve xml formatting using XmlDocument

I am using XmlDocument to work with xml
How do I save my "XmlDocument" with my current formatting?
Current formatting:
<?xml version="1.0" encoding="utf-8"?>
<root>
<element></element>
</root>
Code:
XmlDocument testDoc = new XmlDocument();
testDoc.Load(#"C:\Test.xml");
**(do reading/writing using only XmlDocument methods)**
testDoc.Save(#"C:\Test.xml");
There is a similar topic:
XmlDocument class is removing formatting, c#, .NET
The accepted answer is PreserveWhiteSpace = true, which in reality removes all whitespaces instead of preserving them.
Example:
Code:
XmlDocument testDoc = new XmlDocument();
testDoc.Load(#"C:\Test.xml");
testDoc.PreserveWhitespace = true;
testDoc.Save(#"C:\Test.xml");
Result:
<?xml version="1.0" encoding="utf-8"?><root><element></element></root>
Setting PreserveWhitespace to true works for me - but you've got to do it before loading so that the whitespace doesn't get thrown away at load time:
using System;
using System.Xml;
class Test
{
static void Main()
{
XmlDocument testDoc = new XmlDocument();
testDoc.PreserveWhitespace = true;
testDoc.Load("Test.xml");
testDoc.Save("Output.xml");
}
}
I've just tried that, and the whitespace was preserved.
Umm. I'm seeing whitespace being preserved when using PreserveWhiteSpace=true. Perhaps it was false when you loaded?
var xmlStr = #"<?xml version=""1.0"" encoding=""utf-8""?>
<root>
<element></element>
</root>";
var xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(xmlStr);
xmlDoc.Save(Console.Out);
Shows:
<?xml version="1.0" encoding="utf-16"?>
<root>
<element></element>
</root>
use preservewhitespace before you load. It will keep formatting same
like above
var xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(xmlStr);
if you will use it after loading. it will kill white spaces in between

How to add xml-stylesheet tags to an XML file using C#?

I need to add the following code to the beginning of an XML file, while creating it:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="colors.xslt"?>
I'm sure there is a method for this, but I haven't found it yet. I'm using C#.
Thank you
XmlDocument.CreateProcessingInstruction Method
public static void Main()
{
var doc = new XmlDocument();
doc.AppendChild(doc.CreateProcessingInstruction(
"xml-stylesheet",
"type='text/xsl' href='colors.xslt'"));
}
For LINQ XDocument you can use this:
XDocument xDoc = new XDocument();
xDoc.Add(new XProcessingInstruction("xml-stylesheet",
"type=\"text/xsl\" href=\"xml-style.xslt\""));

Create new XmlDocument from existing XmlDocument Data in Asp.Net

I have an XmlDocument that is from a webservice, and I want to use a subset of the xml to populate a Gridview control. Unfortunately, it contains extra data that I don't need. So I want to create a new XmlDocument from a subset of the existing xml document.
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument xmlDoc = Object.ReturnsXmlDocument;
XmlDocument xmlDocResults = ??? //<results><result></result></results>
}
Basically, I want to create a new XmlDocument with the as the root element. Below is a shortened example of the original xml doc:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<query_time>.12</query_time>
<number_results>3</number_results>
<results>
<result><id>1</id></result>
<result><id>2</id></result>
<result><id>3</id> </result>
</results>
</xml>
Anthony's code helped point me in the right direction, but this is what actually worked for me.
XmlDocument xmlResults = new XmlDocument();
XmlDeclaration xmlDec = xmlResults.CreateXmlDeclaration("1.0", "utf-8", null);
XmlElement rootNode = xmlResults.CreateElement("results");
xmlResults.InsertBefore(xmlDec, xmlResults.DocumentElement);
xmlResults.AppendChild(rootNode);
XmlNode node = xmlDoc.GetElementsByTagName("results")[0];
xmlResults.GetElementsByTagName("results")[0].InnerXml = node.InnerXml.ToString();
What you need is ImportNode:-
XmlDocument xmlDoc = Object.ReturnsXmlDocument;
XmlDocument xmlResults = new XmlDocument();
xmlResults.AppendNode(xmlResults.ImportNode(xmlDoc.SelectSingleNode("/xml/results"));
Untested, but this should be pretty darn close:
XPathDocument original = new XPathDocument("original.xml");
XPathNavigator navigator = original.CreateNavigator();
navigator.MoveToChild("results", "");
XmlWriter results = XmlWriter.Create("results.xml");
navigator.WriteSubtree(results);
results.Close();
And then you can do whatever you need to with the XmlWriter - I'm not sure if you're trying to create the results XmlDocument on disk or not.

Categories

Resources