XDocument.Save() without header - c#

I am editing csproj files with Linq-to-XML and need to save the XML without the <?XML?> header.
As XDocument.Save() is missing the necessary option, what's the best way to do this?

You can do this with XmlWriterSettings, and saving the document to an XmlWriter:
XDocument doc = new XDocument(new XElement("foo",
new XAttribute("hello","world")));
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
StringWriter sw = new StringWriter();
using (XmlWriter xw = XmlWriter.Create(sw, settings))
// or to write to a file...
//using (XmlWriter xw = XmlWriter.Create(filePath, settings))
{
doc.Save(xw);
}
string s = sw.ToString();

A simpler solution than the accepted answer is to use XDocument.ToString() to get the XML text without the header.
Example:
// Load the file
XDocument xDocument = XDocument.Load(fileName);
// Edit the XML...
// Save the edited XML text to file
File.WriteAllText(fileName, xDocument.ToString());

Related

Token StartElement in state Epilog would result in an invalid XML document

I am getting the error "Token StartElement in state Epilog would result in an invalid XML document." when i get the data from datatable and try to convery it to xml file .
Code :
DataTable dtTest = new DataTable();
dtTest.Columns.Add("Name");
dtTest.Columns.Add("NickName");
dtTest.Columns.Add("Code");
dtTest.Columns.Add("reference");
dtTest.Rows.Add("Yash", "POPs", "Vapi", "None1");
dtTest.Rows.Add("shilpa", "shilpa", "valsad", "None2");
dtTest.Rows.Add("Dinesh", "dinu", "pune", "None3");
dtTest.Rows.Add("rahul", "mady", "pardi", "None4");
XmlWriterSettings settings = new XmlWriterSettings();
StringWriter stringwriter = new StringWriter();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stringwriter);
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.WriteStartDocument();
foreach (var row in dtTest.AsEnumerable())
{
xmlTextWriter.WriteStartElement("");
xmlTextWriter.WriteAttributeString("orderid", row.Field<string>("Name"));
xmlTextWriter.WriteElementString("type", row.Field<string>("Name"));
xmlTextWriter.WriteElementString("status", row.Field<string>("Name"));
xmlTextWriter.WriteElementString("productno", row.Field<string>("Name"));
xmlTextWriter.WriteEndElement();
}
XmlDocument docSave = new XmlDocument();
docSave.LoadXml(stringwriter.ToString());
What is the cause of this error, and how can it be fixed?
You have a few problems here:
You are writing multiple root elements to your document, one for each call to xmlTextWriter.WriteStartElement(""). However, a well-formed XML document must have one and only one root element, so you need to wrap your row elements in some container element.
(You might have been thinking that WriteStartDocument() would write the root element, but it does not. It just writes the XML declaration.)
You are using XmlTextWriter but this class is deprecated. From the docs:
Starting with the .NET Framework 2.0, we recommend that you create XmlWriter instances by using the XmlWriter.Create method and the XmlWriterSettings class to take advantage of new functionality.
If you switch to XmlWriter you will get clearer error messages and better error checking.
You are trying to write elements with no name:
xmlTextWriter.WriteStartElement("");
This would result in malformed XML. XmlTextWriter seems not to check for this, but XmlWriter does.
Putting all of the above together, your code can be modified as follows:
var stringwriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { Indent = true }))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
foreach (var row in dtTest.AsEnumerable())
{
xmlWriter.WriteStartElement("Row");
xmlWriter.WriteAttributeString("orderid", row.Field<string>("Name"));
xmlWriter.WriteElementString("type", row.Field<string>("Name"));
xmlWriter.WriteElementString("status", row.Field<string>("Name"));
xmlWriter.WriteElementString("productno", row.Field<string>("Name"));
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
}
var xml = stringwriter.ToString();
Demo fiddle here.

Inserting new data into xml from datatable

I have an xml file about 900MB and i want to insert data from datatable to that existing xml.
There is a way to do this by using load and save like below;
XDocument xdoc = XDocument.Load(FilePath);
var root = xdoc.Descendants("DocumentElement").FirstOrDefault()
if (root != null){
root.Add(new XElement("tag", "value"));
xdoc.Save(FilePath);
}
However, its cost too much. Loading 900MB xml into datatable can cause memory exceptions and poor performance for couple of new rows.
How can i add new rows to big existing xml from datatable?
XDocument (and XmlDocument as well) loads whole file into memory. You should use XmlWriter with combination of XNode.WriteTo method
Example from XNode.WriteTo documentation:
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
using (XmlWriter xw = XmlWriter.Create(sb, xws))
{
XElement child2 = new XElement("AnotherChild",
new XElement("GrandChild", "different content"));
child2.WriteTo(xw);
xw.WriteEndElement();
}
Console.WriteLine(sb.ToString());
You can read big xml documents in the same way, check example in XNode.ReadFrom documentation

.net: XmlDocument creates one line xml document

I have a standard XML document, which looks like a 'tree'. I add some nodes and save changes:
XmlDocument doc = new XmlDocument();
doc.Load(filename);
...
doc.PreserveWhitespace = true;
XmlTextWriter writer = new XmlTextWriter(filename, Encoding.Default);
doc.WriteTo(writer);
writer.Close();
and after that xml document stretch into one line. How to add line feeds?
After you construct the XmlTextWriter, but before you call doc.WriteTo(writer);, insert this line:
writer.Formatting = Formatting.Indented;

Why are all of my line-breaks changing from "/r/n" to "/n/" and how can I stop this from happening?

I am saving my files as xml documents, using XDocument.Save(path), and after saving and loading a document all of the line breaks have changed from "/r/n" to "/n/". Why is this happening and how can I fix it?
You can use XmlWriterSettings to control what your line-break characters are:
XmlWriterSettings xws = new XmlWriterSettings();
xws.NewLineChars = "\r\n";
using (XmlWriter xw = XmlWriter.Create("whatever.xml", xws))
{
xmlDocumentInstance.Save(xw);
}
Whatever you're using to read in your XML might be normalizing your line endings.
If you set the PreserveWhiteSpace property on your XmlDocument object before calling Load() and Save() then this will not happen:
var doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("foo.xml");
...
doc.Save("bar.xml"); // Line endings will not be altered

Make xml more readable

Is there any way to take an xml string in .net and make it easyer to read?
what i mean is can i convert this:
<element1><element2>some data</element2></element1>
to this:
<element1>
<element2>
some data
</element2>
</element1>
is there any built in class for this? as sql server 2005 seems to remove all formatting on xml to save space or some thing...
If you're using .NET 3.5, you can load it as an XDocument and then just call ToString() which will indent it appropriately. For example:
using System;
using System.Xml.Linq;
public class Test
{
static void Main()
{
string xml = "<element1><element2>some data</element2></element1>";
XDocument doc = XDocument.Parse(xml);
xml = doc.ToString();
Console.WriteLine(xml);
}
}
Result:
<element1>
<element2>some data</element2>
</element1>
If you're writing it to a file or other stream, then XDocument.Save will (by default) indent it too.
(I believe XElement has all the same features, if you don't really need an XDocument.)
How do you save / write the XML back to a file ?
You can create an XmlWriter and pass it an XmlWriterSettings instance, where you set the Indent property to true:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create (outputStream, settings);
You can load the string into an XDocument object and save it to a string again:
XDocument doc = XDocument.Load(new StringReader(xmlString));
StringWriter writer = new StringWriter();
doc.Save(writer);
string readable = writer.ToString();
That will give you the xml formatted this way:
<?xml version="1.0" encoding="utf-16"?>
<element1>
<element2>some data</element2>
</element1>
Have a look at
XmlWriterSettings
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.aspx
you can define Indent and IndentChars
First of all, you have tagged C# and VB.NET both. So my answer will be for both of them.
You can define function which get XML string as a parameter in type of String.
Let's say;
You created a function as :
[VB]
Private Function PrettyXML(XMLString As String) As String
Dim sw As New StringWriter()
Dim xw As New XMLWriter(sw)
xw.Formatiing = Formatting.Indented
xw.Indentation = 4
Dim doc As New XMLDocument
doc.LoadXML(XMLString)
doc.Save(xw)
Return sw.ToString()
End Function
Then you can simpyl call this function as:
Dim myXML As String = "<element1><element2>some data</element2></element1>"
Dim myPrettyXML As String
myPrettyXML = PrettyXML(myPrettyXML)
[C#]
Private String PrettyXML(string XMLString)
{
StringWriter sw = new StringWriter();
XMLTextWriter xw = new XmlTextWriter(sw);
xw.Formatiing = Formatting.Indented;
xw.Indentation = 4;
XmlDocument doc = new XmlDocument();
doc.Save(xm);
return sw.ToString();
}
Then you can simply call this function as:
string myXML = "<element1><element2>some data</element2></element1>";
string myPrettyXML = "";
myPrettyXML = PrettyXML(myPrettyXML);
NOTE: I have not tried C# version, but it should work.
Hope this helps..

Categories

Resources