XmlWriter to Write to a String Instead of to a File
You need to create a StringWriter, and pass that to the XmlWriter.
The string overload of the XmlWriter.Create is for a filename.
E.g.
using (var sw = new StringWriter()) {
using (var xw = XmlWriter.Create(sw)) {
// Build Xml with xw.
}
return sw.ToString();
}
XML Writer stored results to string
Just use overloaded method XmlWriter.Create(StringBuilder output)
to create xml string. In this case all output will be written to StringBuilder
instead of file:
StringBuilder builder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(builder);
//... build xml here
string xml = builder.ToString();
Also you can write xml to MemoryStream
with XmlWriter.Create(Stream output)
.
Stream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
// ... build xml here
stream.Position = 0;
string xml = new StreamReader(stream).ReadToEnd();
UPDATE
Extension method below will generate your xml string. By default it uses first column as element names, but you can pass any column index for column with meta data. Also I use table name to generate "Employees" tag, so provide name when you create data table DataTable dt = new DataTable("Employees");
.
public static string ToXml(this DataTable table, int metaIndex = 0)
{
XDocument xdoc = new XDocument(
new XElement(table.TableName,
from column in table.Columns.Cast<DataColumn>()
where column != table.Columns[metaIndex]
select new XElement(column.ColumnName,
from row in table.AsEnumerable()
select new XElement(row.Field<string>(metaIndex), row[column])
)
)
);
return xdoc.ToString();
}
Usage is very simple:
string xml = dt.ToXml();
Output:
<Employees>
<Product_Name>
<hello1>product1</hello1>
<hello2>product2</hello2>
<hello3>product3</hello3>
<hello4>product4</hello4>
</Product_Name>
<product_Price>
<hello1>111</hello1>
<hello2>222</hello2>
<hello3>333</hello3>
<hello4>444</hello4>
</product_Price>
</Employees>
XmlWriter to both String and File
You could create a method like this:
private static void WriteXML(TextWriter writer)
{
using (var xw = XmlWriter.Create(writer))
{
// Build the xml
}
}
And then call it like:
using (StreamWriter sw = new StreamWriter(...))
WriteXML(sw);
to write a file or
string xml = String.Empty;
using (StringWriter sw = new StringWriter())
{
WriteXML(sw);
xml = sw.ToString();
}
To create the string.
You could even create helper methods:
private static void WriteXMLFile(string fileName)
{
using (StreamWriter sw = new StreamWriter(...))
WriteXML(sw);
}
private static string GetXML()
{
using (StringWriter sw = new StringWriter())
{
WriteXML(sw);
return sw.ToString();
}
}
Parsing XmlTextWriter object to String
The following function will extract the string from the System.Xml.XmlTextWriter
objects you've created as Head
and Body
.
private string XmlTextWriterToString(XmlTextWriter writer)
{
// Ensure underlying stream is flushed.
writer.Flush();
// Reset position to beginning of stream.
writer.BaseStream.Position = 0;
using (var reader = new StreamReader(writer.BaseStream))
{
// Read and return content of stream as a single string
var result = reader.ReadToEnd();
return result;
}
}
Some caveats here are that the underlying System.IO.Stream
object associated with the System.Xml.XmlTextWriter
must support both 'read' and 'seek' operations (i.e., both Stream.CanRead
and System.CanSeek
properties must return true
, respectively).
I've made the following edits to your original code:
- Replaced the
Convert.ToString
() calls with calls to this new function. - Made an assumption that you're intending to write to the file specified by the
filepath
parameter to yourSaveAsHTML
() function, and not the hard-coded path. - Wrapped the creation (and use, and disposal) of the
System.Xml.XmlTextWriter
in ausing
block (if you're not familiar, see What are the uses of “using” in C#?).
Following is your code with those changes.
public void SaveAsHTML(string filepath)
{
using (var html = new XmlTextWriter(filepath, System.Text.Encoding.UTF8))
{
html.WriteStartDocument();
html.WriteStartElement("html");
html.WriteRaw(XmlTextWriterToString(Head));
html.WriteRaw(XmlTextWriterToString(Body));
html.WriteEndElement();
html.WriteEndDocument();
html.Flush();
html.Close();
}
}
Another thing of which to be mindful is that, not knowing for sure from the code provided how they're being managed, the lifetimes of Head
and Body
are subject to the same exception-based resource leak potential that html
was before wrapping it in the using
block.
A final thought: the page for System.Xml.XmlTextWriter
notes the following: 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.
How To Write A String(XML Node formatted without root) as nodes using XMLWriter in C#?
You must specify ConformanceLevel
because your xml has no root element.
Also always should dispose all used resources.
using (XmlWriter writer = XmlWriter.Create(@"C:\\Test.XML"))
{
writer.WriteStartDocument();
writer.WriteStartElement("Test");
string scontent = "<A a=\"Hello\"></A><B b=\"Hello\"></B>";
var settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (StringReader stringReader = new StringReader(scontent))
using (XmlReader xmlReader = XmlReader.Create(stringReader, settings))
{
writer.WriteNode(xmlReader, true);
}
writer.WriteEndElement();
}
In addition, you can use XmlWriterSettings
to add indents.
Write to existing xml file without replacing it's contents (XmlWriter)
XML files are just sequential text files. They are not a database or a random-access file. There is no way to just write into the middle of them.
Related Topics
How to Best Implement Equals for Custom Types
How to List All Variables of Class
How to Add an Event to a Usercontrol in C#
Get the Active Color of Windows 8 Automatic Color Theme
Ref and Out Parameters in C# and Cannot Be Marked as Variant
Count the Number of Times a String Appears Within a String
Custom Attribute on Property - Getting Type and Value of Attributed Property
Anonymous Types - Are There Any Distingushing Characteristics
Overriding Savechanges and Setting Modifieddate, But How to Set Modifiedby
Characters in String Changed After Downloading HTML from the Internet
Does C# Support Multiple Inheritance
Openxml Sdk Returning a Number for Cellvalue Instead of Cells Text
Iterating Through All Nodes in Xml File