preview my XML StringWriter in default browser - c#

Good morning everyone. I wrote a very simple class in C# that generates an html file and return it in a string. I want to write a new class that will display this file in default browser. Could you tell me how can I do it?
public class Class1
{
public string HTMLGen(int number)
{
var html = string.Format("<p>testing my {0} html code</p>", number);
var xDocument = new XDocument(
new XDocumentType("html", null, null, null),
new XElement("html",
new XElement("head"),
new XElement("body",
XElement.Parse(html)
)
)
);
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true,
IndentChars = "\t"
};
using (var sw = new StringWriter())
{
using (var writer = XmlWriter.Create(sw, settings))
{
xDocument.WriteTo(writer);
}
return sw.ToString();
}
}
}

Related

XML Writer - Unable to override UTF16 to UTF8

I'm trying to build the XML using XMLWriter but it contains encoding UTF-16. I tried so solution to modify that to UTF-8. But nothing is working
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
Try to override the UTF8String Writer
private class UTF8StringWriter : StringWriter
{
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}
Try to use XDEclaration.
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement("root", new XAttribute("note", "boogers"))
);
using (var writer = new XmlTextWriter(".\\test.xml", new UTF8Encoding(false)))
{
doc.Save(writer);
}

XmlWriter writing empty stringbuilder

I had the following code which "worked" for my testing but I didn't like the formatting:
System.Diagnostics.Debug.WriteLine("----------------------------- Start 1 ----------------------------");
using (var sw = new Utf8StringWriter())
//StringBuilder sb = new StringBuilder();
//using (XmlWriter xw = XmlWriter.Create(sb, new XmlWriterSettings() { Encoding = Encoding.UTF8, Indent = true, IndentChars = "\t" }))
{
XDocument d = new XDocument(new XDeclaration(version: "1.0", encoding: "UTF-8", standalone: "no"));
XElement DMTStandardIF = new XElement("DMTStandardIF", new XAttribute("version", "1.00"));
d.Add(DMTStandardIF);
XElement last = DMTStandardIF;
last.Add(last = new XElement("Thing1", "thing 1 stuff"));
last.Add(null);
last.Add(last = new XElement("Thing2", "thing 2 stuff"));
last.Add(null);
d.Save(sw);
//d.WriteTo(xw);
System.Diagnostics.Debug.WriteLine(sw);
//System.Diagnostics.Debug.WriteLine(sb.ToString());
}
// So I changed it to the following which outputs nothing; xw has content but sb is empty.
System.Diagnostics.Debug.WriteLine("----------------------------- Start 2 ----------------------------");
StringBuilder sb = new StringBuilder();
using (XmlWriter xw = XmlWriter.Create(sb, new XmlWriterSettings() { Encoding = Encoding.UTF8, Indent = true, IndentChars = "\t" }))
{
XDocument d = new XDocument(new XDeclaration(version: "1.0", encoding: "UTF-8", standalone: "no"));
XElement DMTStandardIF = new XElement("DMTStandardIF", new XAttribute("version", "1.00"));
d.Add(DMTStandardIF);
XElement last = DMTStandardIF;
last.Add(last = new XElement("Thing1", "thing 1 stuff"));
last.Add(null);
last.Add(last = new XElement("Thing2", "thing 2 stuff"));
last.Add(null);
d.WriteTo(xw);
//d.Save(xw); // I tried this too and .. empty as well
System.Diagnostics.Debug.WriteLine(sb.ToString());
}
System.Diagnostics.Debug.WriteLine("------------------------------ Done ------------------------------");
Here's what you'll get if you run that:
----------------------------- Start 1 ----------------------------
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<DMTStandardIF version="1.00">
<Thing1>thing 1 stuff<Thing2>thing 2 stuff</Thing2></Thing1>
</DMTStandardIF>
----------------------------- Start 2 ----------------------------
------------------------------ Done ------------------------------
WHY does the second version output nothing? How do I fix it?
This all started because I wanted to test what happens if I attempt myXElement.Add(null) and I already answered that question but I saw XmlWriter writing empty down the rabbit hole and went after it.
Your code doesn't print anything because when you call the Debug.WriteLine the StringBuilder has not yet received the buffer from the XmlWriter. This happens (probably with a call to xw.Flush()) when your code exits from the using statement
Just move the print of the StringBuilder outside the using statement
using (XmlWriter xw = XmlWriter.Create(sb, new XmlWriterSettings() { Encoding = Encoding.UTF8, Indent = true, IndentChars = "\t" }))
{
....
d.WriteTo(xw);
}
System.Diagnostics.Debug.WriteLine(sb.ToString());
System.Diagnostics.Debug.WriteLine("------------------------------ Done --------------------");
In alternative you can force a Flush on the XmlWriter inside the using statement just before printing the StringBuilder.
using (XmlWriter xw = XmlWriter.Create(sb, new XmlWriterSettings() { Encoding = Encoding.UTF8, Indent = true, IndentChars = "\t" }))
{
....
d.WriteTo(xw);
xw.Flush();
System.Diagnostics.Debug.WriteLine(sb.ToString());
}
System.Diagnostics.Debug.WriteLine("------------------------------ Done --------------------");
But in this context it seems pointless and redundant (it will be called again) considering that the code exits the using statement just on the next line.

Serializing WITHOUT xmlns

I have a couple extension methods that handle serialization of my classes, and since it can be a time consuming process, they are created once per class, and handed out by this method.
public static XmlSerializer GetSerializerFor(Type typeOfT)
{
if (!serializers.ContainsKey(typeOfT))
{
var xmlAttributes = new XmlAttributes();
var xmlAttributeOverrides = new XmlAttributeOverrides();
System.Diagnostics.Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));
xmlAttributes.Xmlns = false;
xmlAttributeOverrides.Add(typeOfT, xmlAttributes);
var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides);
serializers.Add(typeOfT, newSerializer);
}
return serializers[typeOfT];
}
This is called by the extension method .Serialize()
public static XElement Serialize(this object source)
{
try
{
var serializer = XmlSerializerFactory.GetSerializerFor(source.GetType());
var xdoc = new XDocument();
using (var writer = xdoc.CreateWriter())
{
serializer.Serialize(writer, source, new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") }));
}
return (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing");
}
catch (Exception x)
{
return new XElement("Error", x.ToString());
}
}
Unfortunately, when Serializing classes that are auto-generated, they have the attribute XmlTypeAttribute(Namespace="http://tempuri.org/") applied to them.
This causes the deserialization by the the non-auto-generated counterparts to fail.
I need the serializer to completely ignore and not apply the namespace, but what I have written in the first block of code doesn't seem to remove it, I still end up with xml like this
<Note>
<ID xmlns="http://tempuri.org/">12</ID>
<Author xmlns="http://tempuri.org/">
<ID>1234</ID>
<Type>Associate</Type>
<IsAvailable>false</IsAvailable>
</Author>
<Created xmlns="http://tempuri.org/">2010-06-22T09:38:01.5024351-05:00</Created>
<Text xmlns="http://tempuri.org/">This is an update</Text>
</Note>
Instead of the same, minus the xmlns="http://tempuri.org/" attribute.
Please help, thanks, this is driving me crazy!
EDIT:
I know the problem, just not how to fix it.
My class, isn't just full of simple types.
It contains properties with types of other classes. Which are also auto-generated with the XmlTypeAttribute(Namespace = "http://tempuri.org/") attribute. So what is happening, is that when serialization occurs, and it serializes the properties of my class, they aren't going through my custom serialization, and thus, are having the attribute applied and not overridden.
Now I just need to figure out how to jump that hoop. Any thoughts as to how?
EDIT 2:
The following works to serialize WITHOUT xmlns... but I'm having a problem on the deserialization end, just not yet sure if it's related or not
public static XmlSerializer GetSerializerFor(Type typeOfT)
{
if (!serializers.ContainsKey(typeOfT))
{
var xmlAttributes = new XmlAttributes();
var xmlAttributeOverrides = new XmlAttributeOverrides();
System.Diagnostics.Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));
xmlAttributes.XmlType = new XmlTypeAttribute
{
Namespace = ""
};
xmlAttributes.Xmlns = false;
var types = new List<Type> {typeOfT, typeOfT.BaseType};
foreach (var property in typeOfT.GetProperties())
{
types.Add(property.PropertyType);
}
types.RemoveAll(t => t.ToString().StartsWith("System."));
foreach (var type in types)
{
xmlAttributeOverrides.Add(type, xmlAttributes);
}
var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides);
//var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides, extraTypes.ToArray(), new XmlRootAttribute(), string.Empty);
//var newSerializer = new XmlSerializer(typeOfT, string.Empty);
serializers.Add(typeOfT, newSerializer);
}
return serializers[typeOfT];
}
EDIT3:
Ended up using solution from
How to remove all namespaces from XML with C#?
public static XElement RemoveAllNamespaces(this XElement source)
{
return !source.HasElements
? new XElement(source.Name.LocalName)
{
Value = source.Value
}
: new XElement(source.Name.LocalName, source.Elements().Select(el => RemoveAllNamespaces(el)));
}
A working solution, for the record!
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
var serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);
No problem - just pass an empty string as the default namespace to the XML serializer:
XmlSerializer newSerializer =
new XmlSerializer(typeOfT, "");
Unfortunately, there's no easy constructor overload if you really need to define the XmlAttributeOverrides and the default namespace - so either you can skip the XmlAttributeOverrides and use that constructor I mentioned, or you need to use the one that defines all possible parameters (including XmlAttributeOverrides and default XML namespaces - and a few more).
public static byte[] SerializeByteByType(object objectToSerialize, Type type)
{
XmlWriterSettings xmlSetting = new XmlWriterSettings()
{
NewLineOnAttributes = false,
OmitXmlDeclaration = true,
Indent = false,
NewLineHandling = NewLineHandling.None,
Encoding = Encoding.UTF8,
NamespaceHandling = NamespaceHandling.OmitDuplicates
};
using (MemoryStream stm = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(stm, xmlSetting))
{
var xmlAttributes = new XmlAttributes();
var xmlAttributeOverrides = new XmlAttributeOverrides();
xmlAttributes.Xmlns = false;
xmlAttributes.XmlType = new XmlTypeAttribute() { Namespace = "" };
xmlAttributeOverrides.Add(type, xmlAttributes);
XmlSerializer serializer = new XmlSerializer(type, xmlAttributeOverrides);
//Use the following to serialize without namespaces
XmlSerializerNamespaces xmlSrzNamespace = new XmlSerializerNamespaces();
xmlSrzNamespace.Add("", "");
serializer.Serialize(writer, objectToSerialize, xmlSrzNamespace);
stm.Flush();
stm.Position = 0;
}
return stm.ToArray();
}
}
public static string SerializeToXml(object obj)
{
UTF8Encoding encoding = new UTF8Encoding(false);
var xmlAttributes = new XmlAttributes();
xmlAttributes.Xmlns = false;
xmlAttributes.XmlType = new XmlTypeAttribute() { Namespace = "" };
var xmlAttributeOverrides = new XmlAttributeOverrides();
var types = obj.GetType().Assembly.GetTypes().Where(t => string.Equals(t.Namespace, obj.GetType().Namespace, StringComparison.Ordinal));
foreach (var t in types) xmlAttributeOverrides.Add(t, xmlAttributes);
XmlSerializer sr = new XmlSerializer(obj.GetType(), xmlAttributeOverrides);
MemoryStream memoryStream = new MemoryStream();
StreamWriter writer = new StreamWriter(memoryStream, encoding);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
// get the stream from the writer
memoryStream = writer.BaseStream as MemoryStream;
sr.Serialize(writer, obj, namespaces);
// apply encoding to the stream
return (encoding.GetString(memoryStream.ToArray()).Trim());
}
It will even work for complex object containing nested object
Credits to user3444796 and Mentor
Working solution (without empty xmlns attribute):
var ns = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
XmlSerializer serializer = new XmlSerializer(typeof(XmlInfo));
XmlDocument doc = new XmlDocument();
using (var ms = new MemoryStream()) {
serializer.Serialize(ms, this, ns);
ms.Position = 0;
doc.Load(ms);
}

How to create an XML document from a .NET object?

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;
}

disabling namespace attributes in serialization

Am using following code to deserialize an object,
using (MemoryStream memoryStream = new MemoryStream())
{
try
{
XmlWriterSettings writerSettings1 = new XmlWriterSettings();
writerSettings1.CloseOutput = false;
writerSettings1.Encoding = System.Text.Encoding.UTF8;
writerSettings1.Indent = false;
writerSettings1.OmitXmlDeclaration = true;
XmlWriter writer1 = XmlWriter.Create(memoryStream, writerSettings1);
XmlSerializer xs1 = new XmlSerializer(obj.GetType(), string.Empty);
xs1.UnknownAttribute += new XmlAttributeEventHandler(xs1_UnknownAttribute);
xs1.UnknownElement += new XmlElementEventHandler(xs1_UnknownElement);
xs1.UnknownNode += new XmlNodeEventHandler(xs1_UnknownNode);
xs1.UnreferencedObject += new UnreferencedObjectEventHandler(xs1_UnreferencedObject);
xs1.Serialize(writer1, obj);
writer1.Close();
}
catch (InvalidOperationException)
{
return null;
}
memoryStream.Position = 0;
serializeObjectDoc.Load(memoryStream);
return serializeObjectDoc.DocumentElement;
After this when i check the returning node i get two extra attributes
{Attribute, Name="xmlns:xsi", Value="http://www.w3.org/2001/XMLSchema-instance"} object {System.Xml.XmlAttribute}
{Attribute, Name="xmlns:xsd", Value="http://www.w3.org/2001/XMLSchema"} object {System.Xml.XmlAttribute}
I want to know how to disable these two attributes
XmlSerializerNamespaces to the rescue; a simple (but complete) example:
using System.Xml.Serialization;
using System;
public class Foo
{
public string Bar { get; set; }
static void Main()
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer ser = new XmlSerializer(typeof(Foo));
ser.Serialize(Console.Out, new Foo { Bar = "abc" }, ns);
}
}

Categories