Thursday, July 31, 2008

XML Fluent Interface

Mark S. Rasmussen recently posted a wonderful way of writing out XML text in .Net simply, I found it amazingly useful for Flash development to take data and make XML files for consumption of the swf file. Several of the commentor's mentioned some improvements that could be made to the class, so I took his class and modified it.

The changes were sometime superficial, like I renamed some of the properties to names that made a little more sense (i.e., within renamed to ParentOf). Where as some of the changes were more to the core of the class, like where he used XmlDocument to write the XML, I used XmlTextWriter which made node stack management much easier. I agreed with his thought though that sometimes you don't want raw XML but you want to manipulate it still. So I added properties to output to string, XmlDocument, or XmlTextWriter (though why you'd use the last one I am not sure).

I redid his more complex structure example for you to see below:
---

xOut xo = new xOut()
.XmlDeclaration()
.Node( "root" ).ParentOf()
.Node("user").ParentOf()
.Node("username").InnerText("orca")
.Node("realname").InnerText("Mark S. Rasmussen")
.Node("description").InnerText("I'll handle any escaping (like < & > for example) needs automagically.")
.Node("articles").ParentOf()
.Node("article").Attribute("id", "25").InnerText("Handling DBNulls")
.Node("article").Attribute("id", "26").InnerText("Accessing my privates")
.CloseParent()
.Node("hobbies").ParentOf()
.Node("hobby").InnerText("Fishing")
.Node("hobby").InnerText("Photography")
.Node("hobby").InnerText("Work");


As you can see, it works very similarly to his class. It's not perfect, but ladies and gentlemen here's my class xOut:
---

using System;
using System.Xml;
using System.IO;

public class xOut
{
// The internal XmlWriter that writes the XML.
private XmlTextWriter xw;

//The internal memory stream that holds the XML.
private MemoryStream ms;

// Whether the next node should be created in the scope of the current node.
bool nextNodeChild = true;

public String GetString()
{
xw.WriteEndDocument();
xw.Flush();

ms.Position = 0;

StreamReader sr = new StreamReader(ms);

String XMLString = sr.ReadToEnd();

xw.Close();
ms.Dispose();
sr.Dispose();

return XMLString;
}

public XmlTextWriter GetXmlText()
{
return xw;
}

public XmlDocument GetXmlDoc()
{
xw.WriteEndDocument();
xw.Flush();

ms.Position = 0;

XmlDocument xd = new XmlDocument();
xd.Load(ms);

xw.Close();
ms.Dispose();

return xd;
}

public xOut ParentOf()
{
nextNodeChild = true;

return this;
}

public xOut CloseParent()
{
if (nextNodeChild)
nextNodeChild = false;
else
xw.WriteEndElement();

return this;
}

public xOut XmlDeclaration()
{
ms = new MemoryStream();

xw = new XmlTextWriter(ms, System.Text.Encoding.UTF8);
xw.WriteStartDocument();

return this;
}

public xOut Node(string name)
{
if (nextNodeChild == false)
xw.WriteEndElement();

xw.WriteStartElement(name);

nextNodeChild = false;

return this;
}

public xOut InnerText(string text)
{
return InnerText(text, false);
}

public xOut InnerText(string text, bool useCData)
{
if (useCData)
xw.WriteCData(text);
else
xw.WriteString(text);

return this;
}

public xOut Attribute(string name, string value)
{
xw.WriteAttributeString(name, value);

return this;
}
}

No comments: