1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
public static class ObjectToXmlConverter { #region Class Methods /// <summary> /// Renders the specified serializable obj. /// </summary> /// <param name="serializableObj">The serializable obj.</param> /// <returns></returns> public static string Render<T>(T serializableObj) { if (!typeof (T).IsSerializable) throw new SerializationException(string.Format("{0} is not marked Serializable.", typeof(T))); var xmls = new XmlSerializer(typeof (T)); using (var ms = new MemoryStream()) { var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true, IndentChars = "\t", NewLineChars = Environment.NewLine, ConformanceLevel = ConformanceLevel.Document }; using (var writer = XmlWriter.Create(ms, settings)) { xmls.Serialize(writer, serializableObj); } string xml = Encoding.UTF8.GetString(ms.ToArray()); if (xml.Length > 0 && xml[0] != '<') { xml = xml.Substring(1, xml.Length - 1); } return xml; } } #endregion } public static class XsltTransformer { #region Class Methods /// <summary> /// Renders the specified serializable obj. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="serializableObj">The serializable obj.</param> /// <param name="xsltPath">The XSLT path.</param> public static XmlDocument Render<T>(T serializableObj, string xsltPath) { var rawXml = ObjectToXmlConverter.Render(serializableObj); rawXml = StripInvalidCharacters(rawXml); var document = new XmlDocument(); document.LoadXml(rawXml); var xDoc = XDocument.Load(new XmlNodeReader(document)); var transformedDoc = new XDocument(); using (var writer = transformedDoc.CreateWriter()) { var transform = new XslCompiledTransform(); transform.Load(XmlReader.Create(new StreamReader(xsltPath))); transform.Transform(xDoc.CreateReader(), writer); } var xmlDocument = new XmlDocument(); xmlDocument.Load(transformedDoc.CreateReader()); return xmlDocument; } /// <summary> /// Strips the illegal characters. /// </summary> /// <param name="rawXml">The raw XML.</param> /// <returns></returns> private static string StripInvalidCharacters(string rawXml) { rawXml = rawXml.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("\t", string.Empty); return rawXml; } #endregion }
Refactorings
No refactoring yet !
Ants
September 30, 2009, September 30, 2009 01:33, permalink
I'm not seeing the point of the StripInvalidCharacters() since those characters are perfectly valid as per the XML specifications. Is there a bug in your XSL stylesheet that can't handle those characters?
Anyway, here is my refactoring that doesn't even go through an intermediate string. Everything is kept in an XDocument until the final return of an XmlDocument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
public static class XsltTransformer { static XmlReader Serialize<T>(T serializableObj) { var serialized = new XDocument(); using (var writer = serialized.CreateWriter()) { var xmls = new XmlSerializer(typeof(T)); xmls.Serialize(writer, serializableObj); } return serialized.CreateReader(); } static XmlReader Transform(XmlReader serialized, string xsltPath) { var transformed = new XDocument(); using (var writer = transformed.CreateWriter()) { var transform = new XslCompiledTransform(); transform.Load(xsltPath); transform.Transform(serialized, writer); } return transformed.CreateReader(); } public static XmlDocument Render<T>(T serializableObj, string xsltPath) { var document = new XmlDocument(); document.Load(Transform(Serialize(serializableObj), xsltPath)); return document; } }
Ants
September 30, 2009, September 30, 2009 09:16, permalink
Also if you are into lamba expressions, the parallel code paths between Serialize<T> and Transform<T> can be refactored as below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
public static class XsltTransformer { static XmlReader WriteToReader(Action<XmlWriter> write) { var doc = new XDocument(); using (var writer = doc.CreateWriter()) write(writer); return doc.CreateReader(); } static XmlReader Serialize<T>(T serializableObj) { var xmls = new XmlSerializer(typeof(T)); return WriteToReader(writer => xmls.Serialize(writer, serializableObj)); } static XmlReader Transform(XmlReader serialized, string xsltPath) { var transform = new XslCompiledTransform(); transform.Load(xsltPath); return WriteToReader(writer => transform.Transform(serialized, writer)); } public static XmlDocument Render<T>(T serializableObj, string xsltPath) { var document = new XmlDocument(); document.Load(Transform(Serialize(serializableObj), xsltPath)); return document; } }
I'm using XSLT for document generation and have code to serialize my objects into XML and then apply to the transform. Since I built alot of it based on intellisense suggestions and random postings on the internet I assume it could probably be improved marginally atleast.