I need to take the XML generated by a XmlWriter and modify it. Is it possible?
Being "writer" the XmlWriter, "writeStream" an IOStream and "value" a List of items, here is the code to write with XmlWriter:
writer.WriteRaw("<array>");
writer.WriteRaw("<curLength>" + ((IList)value).Count + "</curLength>");
writer.Close();
serializer = new XmlSerializer(type);
XmlWriter loopWriter;
foreach (object o in (IList)value)
{
loopWriter = XmlWriter.Create(writeStream, new XmlWriterSettings { OmitXmlDeclaration = true });
serializer = new XmlSerializer(o.GetType());
serializer.Serialize(loopWriter, o);
loopWriter.Close();
}
writer = CreateXmlWriter(writeStream, content);
writer.WriteRaw("</array>");
writer.Close();
And after that i want to take the stream generated by the XmlWriter and modify it, doing something like this:
XmlDocument doc = new XmlDocument();
doc.Load(writeStream);
var elements = doc.GetElementsByTagName("struct");
int numberOfElements = elements.Count;
for(int i=1; i<=numberOfElements; i++)
{
XmlNode element = elements.Item(i);
XmlElement indexElement = doc.CreateElement("index");
indexElement.InnerText = i.ToString();
element.InsertAfter(indexElement,element);
}
But, if i execute the code, it throws a "NotSupportedException" at the line of "doc.Load(writeStream);"
Thank you!
Related
I'm converting a JSON string to an XML node like this:
public ActionResult Test(string json)
{
System.Xml.XmlNode myXmlNode = JsonConvert.DeserializeXmlNode("{\"root\":" + json + "}", "root");
How can I save myXmlNode to an external file, say test.xml?
Thanks
This should do it:
var xdoc = XDocument.Load(new StringReader(myXmlNode.ToString()), LoadOptions.None);
xdoc.Save(#"c:\temp\test.xml", SaveOptions.None);
UPDATE:
using (StreamWriter writer = new StreamWriter(Server.MapPath("~/test.xml")))
{
writer.WriteLine(myXmlNode.OuterXml);
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(myXmlNode);
XmlTextWriter writer = new XmlTextWriter("yourfilename.xml",null);
writer.Formatting = Formatting.Indented;
doc.Save(writer);
I have some xml data that looks like..
<Root>
<Data>Nack</Data>
<Data>Nelly</Data>
</Root>
I want to add "<?xml version=\"1.0\"?>" to this string. Then preserve the xml as a string.
I attempted a few things..
This breaks and loses the original xml string
myOriginalXml="<?xml version=\"1.0\"?>" + myOriginalXml;
This doesnt do anything, just keeps the original xml data with no declaration attached.
XmlDocument doc = new XmlDocument();
doc.LoadXml(myOriginalXml);
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8","no");
StringWriter sw = new StringWriter();
XmlTextWriter tx = new XmlTextWriter(sw);
doc.WriteTo(tx);
string xmlString = sw.ToString();
This is also not seeming to have any effect..
XmlDocument doc = new XmlDocument();
doc.LoadXml(myOriginalXml);
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8", "no");
MemoryStream xmlStream = new MemoryStream();
doc.Save(xmlStream);
xmlStream.Flush();
xmlStream.Position = 0;
doc.Load(xmlStream);
StringWriter sw = new StringWriter();
XmlTextWriter tx = new XmlTextWriter(sw);
doc.WriteTo(tx);
string xmlString = sw.ToString();
Use an xmlwritersettings to achieve greater control over saving. The XmlWriter.Create accepts that setting (instead of the default contructor)
var myOriginalXml = #"<Root>
<Data>Nack</Data>
<Data>Nelly</Data>
</Root>";
var doc = new XmlDocument();
doc.LoadXml(myOriginalXml);
var ms = new MemoryStream();
var tx = XmlWriter.Create(ms,
new XmlWriterSettings {
OmitXmlDeclaration = false,
ConformanceLevel= ConformanceLevel.Document,
Encoding = UTF8Encoding.UTF8 });
doc.Save(tx);
var xmlString = UTF8Encoding.UTF8.GetString(ms.ToArray());
I am using an XmlSerializer to serialize an object to xml. After the object gets serialized, I end up with something like...
<?xml version="1.0" encoding="utf-8"?>
<xml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</xml>
I need to have it return simply...
<xml></xml>
Is there a way to serialize xml without the extra information? I realize strictly proper xml requires these additional elements, but I need the simpler form as I am appending these xml strings together to form a larger xml blob.
UPDATE
I was able to get the following code to work...
public static string Serialize(object o)
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(String.Empty, String.Empty);
StringBuilder sb = new StringBuilder();
XmlWriter xmlw = XmlWriter.Create(sb, xws);
XmlSerializer serializer = new XmlSerializer(o.GetType());
serializer.Serialize(xmlw, o, ns);
xmlw.Flush();
return sb.ToString();
}
In C#, you can do something like this:
XmlSerializer serializer = new XmlSerializer(typeof(object));
StringWriter stringWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(stringWriter, new XmlWriterSettings() { OmitXmlDeclaration = true }))
{
serializer.Serialize(writer, this, new XmlSerializerNamespaces() { "",""});
}
string xmlText = stringWriter.ToString();
Explanation:
OmitXmlDeclaration = true makes it remove the declaration.
new XmlSerializerNamespaces() { "",""} removes the namespaces.
I am using the following code to create an xml document -
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
new XmlSerializer(typeof(docket)).Serialize(Console.Out, i, ns);
this works great in creating the xml file with no namespace attributes. i would like to also have no encoding attribute in the root element, but I cannot find a way to do it. Does anyone have any idea if this can be done?
Thanks
Old answer removed and update with new solution:
Assuming that it's ok to remove the xml declaration completly, because it makes not much sense without the encoding attribute:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");
using (XmlWriter writer = XmlWriter.Create(Console.Out, new XmlWriterSettings { OmitXmlDeclaration = true}))
{
new XmlSerializer(typeof (SomeType)).Serialize(writer, new SomeType(), ns);
}
To remove encoding from XML header pass TextWriter with null encoding to XmlSerializer:
MemoryStream ms = new MemoryStream();
XmlTextWriter w = new XmlTextWriter(ms, null);
s.Serialize(w, vs);
Explanation
XmlTextWriter uses encoding from TextWriter passed in constructor:
// XmlTextWriter constructor
public XmlTextWriter(TextWriter w) : this()
{
this.textWriter = w;
this.encoding = w.Encoding;
..
It uses this encoding when generating XML:
// Snippet from XmlTextWriter.StartDocument
if (this.encoding != null)
{
builder.Append(" encoding=");
...
string withEncoding;
using (System.IO.MemoryStream memory = new System.IO.MemoryStream()) {
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(memory)) {
serializer.Serialize(writer, obj, null);
using (System.IO.StreamReader reader = new System.IO.StreamReader(memory)) {
memory.Position = 0;
withEncoding= reader.ReadToEnd();
}
}
}
string withOutEncoding= withEncoding.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
Credit to this blog for helping me with my code
http://blog.dotnetclr.com/archive/2008/01/29/removing-declaration-and-namespaces-from-xml-serialization.aspx
here's my solution, same idea, but in VB.NET and a little clearer in my opinion.
Dim sw As StreamWriter = New, StreamWriter(req.GetRequestStream,System.Text.Encoding.ASCII)
Dim xSerializer As XmlSerializer = New XmlSerializer(GetType(T))
Dim nmsp As XmlSerializerNamespaces = New XmlSerializerNamespaces()
nmsp.Add("", "")
Dim xWriterSettings As XmlWriterSettings = New XmlWriterSettings()
xWriterSettings.OmitXmlDeclaration = True
Dim xmlWriter As XmlWriter = xmlWriter.Create(sw, xWriterSettings)
xSerializer.Serialize(xmlWriter, someObjectT, nmsp)
I have the following variable that accepts a file name:
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
I would like to change it so that I can pass in an object. I don't want to have to serialize the object to file first.
Is this possible?
Update:
My original intentions were to take an xml document, merge some xslt (stored in a file), then output and return html... like this:
public string TransformXml(string xmlFileName, string xslFileName)
{
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
var xslt = new System.Xml.Xsl.XslCompiledTransform();
xslt.Load(xslFileName);
var stm = new MemoryStream();
xslt.Transform(xd, null, stm);
stm.Position = 1;
var sr = new StreamReader(stm);
xtr.Close();
return sr.ReadToEnd();
}
In the above code I am reading in the xml from a file. Now what I would like to do is just work with the object, before it was serialized to the file.
So let me illustrate my problem using code
public string TransformXMLFromObject(myObjType myobj , string xsltFileName)
{
// Notice the xslt stays the same.
// Its in these next few lines that I can't figure out how to load the xml document (xd) from an object, and not from a file....
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
}
You want to turn an arbitrary .NET object into a serialized XML string? Nothing simpler than that!! :-)
public string SerializeToXml(object input)
{
XmlSerializer ser = new XmlSerializer(input.GetType(), "http://schemas.yournamespace.com");
string result = string.Empty;
using(MemoryStream memStm = new MemoryStream())
{
ser.Serialize(memStm, input);
memStm.Position = 0;
result = new StreamReader(memStm).ReadToEnd();
}
return result;
}
That should to it :-) Of course you might want to make the default XML namespace configurable as a parameter, too.
Or do you want to be able to create an XmlDocument on top of an existing object?
public XmlDocument SerializeToXmlDocument(object input)
{
XmlSerializer ser = new XmlSerializer(input.GetType(), "http://schemas.yournamespace.com");
XmlDocument xd = null;
using(MemoryStream memStm = new MemoryStream())
{
ser.Serialize(memStm, input);
memStm.Position = 0;
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
using(var xtr = XmlReader.Create(memStm, settings))
{
xd = new XmlDocument();
xd.Load(xtr);
}
}
return xd;
}
You can serialize directly into the XmlDocument:
XmlDocument doc = new XmlDocument();
XPathNavigator nav = doc.CreateNavigator();
using (XmlWriter w = nav.AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(MyType));
ser.Serialize(w, myObject);
}
Expanding on #JohnSaunders solution I wrote the following generic function:
public XmlDocument SerializeToXml<T>(T source) {
var document = new XmlDocument();
var navigator = document.CreateNavigator();
using (var writer = navigator.AppendChild()) {
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, source);
}
return document;
}