I'm having the following code which is spitting 'Root Element Missing' during doc.Load().
MemoryStream stream = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(stream, Encoding.UTF8);
xmlWriter.Formatting = System.Xml.Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
XmlDocument doc = new XmlDocument();
stream.Position = 0;
doc.Load(stream);
xmlWriter.Close();
I'm not able to figure out the issue. Any insights?
You haven't flushed the xmlWriter, so it may well not have written anything out yet. Also, you're never completing the root element, so even if it has written out
<Root>
it won't have written the closing tag. You're trying to load it as a complete document.
I'm not sure at what point an XmlWriter actually writes out the starting part of an element anyway - don't forget it may have attributes to write too. The most it could write out with the code you've got is <Root.
Here's a complete program which works:
using System;
using System.IO;
using System.Text;
using System.Xml;
class Test
{
static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
{
XmlTextWriter xmlWriter = new XmlTextWriter(stream, Encoding.UTF8);
xmlWriter.Formatting = System.Xml.Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
xmlWriter.WriteEndElement();
xmlWriter.Flush();
XmlDocument doc = new XmlDocument();
stream.Position = 0;
doc.Load(stream);
doc.Save(Console.Out);
}
}
}
(Note that I'm not calling WriteEndDocument - that only seems to be necessary if you still have open elements or attributes.)
What #Skeet said, plus, you don't seem to close your element:
xmlWriter.WriteEndElement();
Well I see you starting the document, but I don't see you ending it or closing it... (at least not before you use it)
Related
I have a strange issue with my XmlDocument class.
I write some XML file with it, which works great.
And I have Save() method:
public void Save()
{
var xwSettings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(false),
Indent = true,
IndentChars = "\t"
};
using (XmlWriter xw = XmlWriter.Create(new FileStream(this.FilePath, FileMode.Create), xwSettings))
{
XmlDocument.WriteTo(xw);
}
}
Like everyone sees, I'm using "using" which should give the xml free :)
But if I try to read this file directly after calling Save() I get the exception:
The process can not access the file "___.xml", because it's already in use by another process.
Can someone explain that to me and give me a solution for it?
Kind regards
You are not disposing your file stream. Try changing your code like this.
using (var xmlStream = new FileStream(this.FilePath, FileMode.Create))
{
using (XmlWriter xw = XmlWriter.Create(xmlStream, xwSettings))
{
var xDoc = new XmlDocument();
xDoc.WriteTo(xw);
}
}
XmlDocument is adding a space at the end of self closing tags, even with PreserveWhitespace set to true.
// This fails
string originalXml = "<sample><node id=\"99\"/></sample>";
// Convert to XML
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml(originalXml);
// Save back to a string
string extractedXml = null;
using (MemoryStream stream = new MemoryStream())
{
doc.Save(stream);
stream.Position = 0;
using(StreamReader reader = new StreamReader(stream))
{
extractedXml = reader.ReadToEnd();
}
}
// Confirm that they are identical
Assert.AreEqual(originalXml, extractedXml);
The desired output is:
<sample><node id="99"/></sample>
But I am getting:
<sample><node id="99" /></sample>
Is there a way to suppress that extra space?
Here's how XmlDocument.Save(Stream) looks like :
public virtual void Save(Stream outStream)
{
XmlDOMTextWriter xmlDomTextWriter = new XmlDOMTextWriter(outStream, this.TextEncoding);
if (!this.preserveWhitespace)
xmlDomTextWriter.Formatting = Formatting.Indented;
this.WriteTo((XmlWriter) xmlDomTextWriter);
xmlDomTextWriter.Flush();
}
So setting PreserveWhiteSpace has no effect on the inside of the nodes. The documentation of the XmlTextWriter says :
When writing an empty element, an additional space is added between tag name and the closing tag, for example . This provides compatibility with older browsers.
So I guess there is no easy way out. Here's a workaround tho:
So I wrote a wrapper class MtxXmlWriter that is derived from XmlWriter and wraps the original XmlWriter returned by XmlWriter.Create() and does all the necessary tricks.
Instead of using XmlWriter.Create() you just call one of the MtxXmlWriter.Create() methods, that's all. All other methods are directly handed over to the encapsulated original XmlWriter except for WriteEndElement(). After calling WriteEndElement() of the encapsulated XmlWriter, " />" is replaced with "/>" in the buffer:
I'm trying to create an xml file. I already set the document and have a result with Xmlwriter when printing to console but when it comes to having an actual .xml file on my desktop I always end up with empty files. Clearly I'm missing something or forgetting something but can't tell on my own.
Below is the piece of my code where it all happens (not).
public void button1_Click(object sender, EventArgs e)
{
XmlDocument dddxml = new XmlDocument();
//XmlDeclaration xmldecl;
//xmldecl = dddxml.CreateXmlDeclaration("1.0", null, null);
//xmldecl.Encoding = "UTF-8";
//xmldecl.Standalone = "yes";
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
StringBuilder builder = new StringBuilder();
writer = XmlWriter.Create(builder, settings);
writer.WriteStartDocument();
writer.WriteStartElement("root");
BlockSelect(0);
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
Console.WriteLine(builder.ToString());
writer = XmlWriter.Create("DddXml.Xml", settings);
dddxml.Save(writer);
File.Create(path);//declared elsewhere, valid file location string
}
You have created new XmlDocument here:
XmlDocument dddxml = new XmlDocument();
But you haven't populated it in the rest of the code and in fact you're not using it and writing xml to string builder using WriteStartDocument and WriteEndElement methods of XmlWriter.
Thus your dddxml remains empty, so when you're trying to save it like this:
dddxml.Save(writer);
, there is nothing to save and you're getting empty file.
So you have to choose - will you use XmlDocument or XmlWriter to create and save your xml.
As commented by #Charles Mager, File.Create() just makes an empty file.
You can try to write directly to the file instead of using StringBuilder. Here's a sample to directly write to the file using the XmlWriter:
XmlWriter writer = XmlWriter.Create("C:\\ddxml.xml", settings);
writer.WriteStartDocument();
writer.WriteStartElement("root");
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
See that the file is written on C:\ddxml.xml.
If you want you can also use LINQ, it's easier :
XDocument doc = new XDocument();
XNamespace ns = "";
doc.Add(new XElement(ns + "root"));
doc.Save(#"C:\DddXml.Xml");
I have an xmlwriter object used in a method. I'd like to dump this out to a file to read it. Is there a straightforward way to do this?
Thanks
Use this code
// Create the XmlDocument.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>");
// Add a price element.
XmlElement newElem = doc.CreateElement("price");
newElem.InnerText = "10.95";
doc.DocumentElement.AppendChild(newElem);
// Save the document to a file and auto-indent the output.
XmlTextWriter writer = new XmlTextWriter(#"C:\data.xml", null);
writer.Formatting = Formatting.Indented;
doc.Save(writer);
As found on MSDN: http://msdn.microsoft.com/en-us/library/z2w98a50.aspx
One possibility is to set the XmlWriter to output to a text file:
using (var writer = XmlWriter.Create("dump.xml"))
{
...
}
Need to generate an html report from XML and corresponding XSL butI have to use memorystream instead of IO File write on server directories. For the most part I managed to create an xml
MemoryStream ms = new MemoryStream();
XmlWriterSettings wSettings = new XmlWriterSettings();
wSettings.Indent = true;
using(XmlWriter writer = XmlWriter.Create(ms,wSettings))
{
/**
creating xml here
**/
writer.Flush();
writer.Close();
}
return ms; // returning the memory stream to another function
// to create html
// This Function creates
protected string ConvertToHtml(MemoryStream xmlOutput)
{
XPathDocument document = new XPathDocument(xmlOutput);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xmlOutput);
StringWriter writer = new StringWriter();
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(reportDir + "MyXslFile.xsl");
transform.Transform(xDoc, null, writer);
xmlOutput.Position = 1;
StreamReader sr = new StreamReader(xmlOutput);
return sr.RearToEnd();
}
Somewhere along the line I am messing up with creating the HTML Report and cant figure out how to send that file to client end. I dont have much experience working with memorystream. So, any help would be greatly appreciated. Thank you.
You're completely bypassing your transform here:
// This Function creates
protected string ConvertToHtml(MemoryStream xmlOutput)
{
XPathDocument document = new XPathDocument(xmlOutput);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xmlOutput);
StringWriter writer = new StringWriter();
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(reportDir + "MyXslFile.xsl");
transform.Transform(xDoc, null, writer);
// These lines are the problem
//xmlOutput.Position = 1;
//StreamReader sr = new StreamReader(xmlOutput);
//return sr.RearToEnd();
return writer.ToString()
}
Also, calling Flush right before you call Close on a writer is redundant as Close implies a flush operation.
It is not clear to me what you want to achieve but using both XmlDocument and XPathDocument to load from the same memory stream does not make sense I think. And I would set the MemoryStream to Position 0 before loading from it so either have the function creating and writing to the memory stream ensure that it sets the Position to zero or do that before you call Load on the XmlDocument or before you create an XPathDocument, depending on what input tree model you want to use.