I have an XMLDocument that I have read in from file. The file is Unicode, and has the newline character '\n'. When I write the XMLDocument back out, it has the newline characters '\r\n'.
Here is the code, pretty simple:
XmlTextWriter writer = new XmlTextWriter(indexFile + ".tmp", System.Text.UnicodeEncoding.Unicode);
writer.Formatting = Formatting.Indented;
doc.WriteTo(writer);
writer.Close();
XmlWriterSettings has a property, NewLineChars, but I am unable to specify the settings parameter on 'writer', it is read-only.
I can create a XmlWriter with a specified XmlWriterSettings property, but XmlWriter does not have a formatting property, resulting in a file with no linebreaks at all.
So, in short, I need to write a Unicode Xml file with newline character '\n' and Formatting.Indented. Thoughts?
I think you're close. You need to create the writer from the settings object:
(Lifted from the XmlWriterSettings MSDN page)
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineOnAttributes = true;
writer = XmlWriter.Create(Console.Out, settings);
writer.WriteStartElement("order");
writer.WriteAttributeString("orderID", "367A54");
writer.WriteAttributeString("date", "2001-05-03");
writer.WriteElementString("price", "19.95");
writer.WriteEndElement();
writer.Flush();
Use XmlWriter.Create() to create the writer and specify the format. This worked well:
using System;
using System.Xml;
class Program {
static void Main(string[] args) {
XmlWriterSettings settings = new XmlWriterSettings();
settings.NewLineChars = "\n";
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(#"c:\temp\test.xml", settings);
XmlDocument doc = new XmlDocument();
doc.InnerXml = "<root><element>value</element></root>";
doc.WriteTo(writer);
writer.Close();
}
}
Related
Okay so I have some code which is supposed to change a value in a configuration file.
string xmlFile = "KeePass.config.xml";
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlWriterSettings settings = new XmlWriterSettings();
settings.IndentChars = "\t";
settings.Indent = true;
xmlDoc.Load(xmlFile);
xmlDoc.SelectSingleNode("Configuration/Application/LastUsedFile").InnerText = fileName;
xmlDoc.Save(xmlFile);
The problem with this is that it indents the XML file with spaces instead of tabs and the program which reads the configuration file needs to see the XML with tab indents. Any help would be appreciated.
Have you tried
xmlDoc.PreserveWhitespace = true;
I am wondering how to add a line break for each element when using XmlSerializer?
Sample code:
XmlSerializer serializer = new XmlSerializer(typeof(xxx));
using (XmlWriter xmlWriter = XmlWriter.Create("test.xml")
{
serializer.Serialize(xmlWriter, xxx);
}
When creating the XmlWriter, pass in an XmlWriterSettings object with Indent set to true.
var xmlWriterSettings = new XmlWriterSettings() { Indent = true };
XmlSerializer serializer = new XmlSerializer(typeof(xxx));
using (XmlWriter xmlWriter = XmlWriter.Create("test.xml", xmlWriterSettings)
{
serializer.Serialize(xmlWriter, xxx);
}
You can use XmlWriterSettings and set the properties to out the indentation and newlines. .Indent and .NewLineOnAttributes seem to be what you would want.
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.aspx
I want to be able to write XML to a String with the declaration and with UTF-8 encoding. This seems mighty tricky to accomplish.
I have read around a bit and tried some of the popular answers for this but the they all have issues. My current code correctly outputs as UTF-8 but does not maintain the original formatting of the XDocument (i.e. indents / whitespace)!
Can anyone offer some advice please?
XDocument xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), xelementXML);
MemoryStream ms = new MemoryStream();
using (XmlWriter xw = new XmlTextWriter(ms, Encoding.UTF8))
{
xml.Save(xw);
xw.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
String xmlString = sr.ReadToEnd();
}
The XML requires the formatting to be identical to the way .ToString() would format it i.e.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<node>blah</node>
</root>
What I'm currently seeing is
<?xml version="1.0" encoding="utf-8" standalone="yes"?><root><node>blah</node></root>
Update
I have managed to get this to work by adding XmlTextWriter settings... It seems VERY clunky though!
MemoryStream ms = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.Indent = true;
using (XmlWriter xw = XmlTextWriter.Create(ms, settings))
{
xml.Save(xw);
xw.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
String blah = sr.ReadToEnd();
}
Try this:
using System;
using System.IO;
using System.Text;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument doc = XDocument.Load("test.xml",
LoadOptions.PreserveWhitespace);
doc.Declaration = new XDeclaration("1.0", "utf-8", null);
StringWriter writer = new Utf8StringWriter();
doc.Save(writer, SaveOptions.None);
Console.WriteLine(writer);
}
private class Utf8StringWriter : StringWriter
{
public override Encoding Encoding { get { return Encoding.UTF8; } }
}
}
Of course, you haven't shown us how you're building the document, which makes it hard to test... I've just tried with a hand-constructed XDocument and that contains the relevant whitespace too.
Try XmlWriterSettings:
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = false;
xws.Indent = true;
And pass it on like
using (XmlWriter xw = XmlWriter.Create(sb, xws))
See also https://stackoverflow.com/a/3288376/1430535
return xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString();
How do remove the BOM from an XML file that is being created?
I have tried using the new UTF8Encoding(false) method, but it doesn't work. Here is the code I have:
XmlDocument xmlDoc = new XmlDocument();
XmlTextWriter xmlWriter = new XmlTextWriter(filename, new UTF8Encoding(false));
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
xmlWriter.WriteStartElement("items");
xmlWriter.Close();
xmlDoc.Load(filename);
XmlNode root = xmlDoc.DocumentElement;
XmlElement item = xmlDoc.CreateElement("item");
root.AppendChild(item);
XmlElement itemCategory = xmlDoc.CreateElement("category");
XmlText itemCategoryText = xmlDoc.CreateTextNode("test");
item.AppendChild(itemCategory);
itemCategory.AppendChild(itemCategoryText);
xmlDoc.Save(filename);
You're saving the file twice - once with XmlTextWriter and once with xmlDoc.Save. Saving from the XmlTextWriter isn't adding a BOM - saving with xmlDoc.Save is.
Just save to a TextWriter instead, so that you can specify the encoding again:
using (TextWriter writer = new StreamWriter(filename, false,
new UTF8Encoding(false))
{
xmlDoc.Save(writer);
}
I'd write the XML to a string(builder) instead and then write that string to file.
I am creating an ASHX that returns XML however it expects a path when I do
XmlWriter writer = XmlWriter.Create(returnXML, settings)
But returnXML is just an empty string right now (guess that won't work), however I need to write the XML to something that I can then send as the response text. I tried XmlDocument but it gave me an error expecting a string. What am I missing here?
If you really want to write into memory, pass in a StringWriter or a StringBuilder like this:
using System;
using System.Text;
using System.Xml;
public class Test
{
static void Main()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("root");
writer.WriteStartElement("element");
writer.WriteString("content");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}
Console.WriteLine(builder);
}
}
If you want to write it directly to the response, however, you could pass in HttpResponse.Output which is a TextWriter instead:
using (XmlWriter writer = XmlWriter.Create(Response.Output, settings))
{
// Write into it here
}
Something was missing on my side: flushing the XmlWriter's buffer:
static void Main()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("root");
writer.WriteStartElement("element");
writer.WriteString("content");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
}
Console.WriteLine(builder);
}
StringBuilder xml = new StringBuilder();
TextWriter textWriter = new StringWriter(xml);
XmlWriter xmlWriter = new XmlTextWriter(textWriter);
Then, use the xmlWriter to do all the xml writing, and that writes it directly to the StringBuilder.
Edit: Thanks to Jon Skeet's comment:
StringBuilder xml = new StringBuilder();
XmlWriter xmlWriter = XmlWriter.Create(xml);
The best way to do that is to write directly to the Response Output Stream. Its a stream that's built-in to ASP.NET to allow you to write whatever output as a stream, in this case you can write XML to it.