XmlDocument fluent interface

I do a lot of backend programming for Flash frontends. That basically means a lot of ASPX pages that simply return some XML and accept some incoming XML for parameters. Most of the UI logic ends up getting cluttered with manual XML stringbuilding, so I saw this as an obvious opportunity to play around with a fluent interfaces.

Now, here's an example of a typical boolean yes/no result from a Flash query:

<?xml version="1.0" encoding="utf-8"?>
<root>
	<result type="boolean">true</result>
</root>

I'd usually create this bit of XML using a simple StringBuilder like so:

StringBuilder output = new StringBuilder();
output.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
output.Append("<root>");
output.Append("<result type=\"boolean\">true</result>");
output.Append("</root>");

This has the advantage of being very fast to write, but readability suffers from the escaped quotes, lack of indentation and there's a whole lot of text when the XML becomes just a bit more advanced.

A "prettier" way is to use the DOM through the XmlDocument like so:

XmlDocument xd = new XmlDocument();
xd.AppendChild(xd.CreateXmlDeclaration("1.0", "utf-8", ""));

XmlNode root = xd.CreateElement("root");
xd.AppendChild(root);

XmlNode result = xd.CreateElement("result");
result.InnerText = "true";

XmlAttribute type = xd.CreateAttribute("type");
type.Value = "boolean";

result.Attributes.Append(type);
root.AppendChild(result);

While this does produce exactly the same XML, it takes up twice as many lines of code, excluding the whitespace lines. Without whitespace it is even more unreadable.

Let me introduce you to my quick'n'simple fluent interface that uses XmlDocument internally, XmlOutput:

XmlOutput xo = new XmlOutput()
	.XmlDeclaration()
	.Node("root").Within()
		.Node("result").Attribute("type", "boolean").InnerText("true");

Using XmlOutput we're down to four lines, the shortest example yet. While linecount is not, and should not be, a measurement of quality, it is preferred. I believe using XmlOutput is, by far, the most readable example.

Basically, using Node() creates a new node within the current node. If no node has been created previously, it will automatically be the root node. Any time a new node is created, it automatically becomes the "current node". Calling Within() moves the context into the current node, thus any newly created nodes will be created within that node. Attribute() will add an attribute to the current node, likewise will InnerText() set the InnerText of the current node. EndWithin() moves the context to the parent node, it is not mandatory for "closing" the nodes, it is only required when you actually need to move the scope.

Let me present you with a couple of examples. Dynamic data:

XmlOutput xo = new XmlOutput()
				.XmlDeclaration()
				.Node("root").Within()
					.Node("numbers").Within();

for (int i = 1; i <= 10; i++)
	xo.Node("number").Attribute("value", i.ToString()).InnerText("This is the number: " + i);

<?xml version="1.0" encoding="utf-8"?>
<root>
	<numbers>
		<number value="1">This is the number: 1</number>
		<number value="2">This is the number: 2</number>
		<number value="3">This is the number: 3</number>
		<number value="4">This is the number: 4</number>
		<number value="5">This is the number: 5</number>
		<number value="6">This is the number: 6</number>
		<number value="7">This is the number: 7</number>
		<number value="8">This is the number: 8</number>
		<number value="9">This is the number: 9</number>
		<number value="10">This is the number: 10</number>
	</numbers>
</root>

And complex structures:

XmlOutput xo = new XmlOutput()
	.XmlDeclaration()
	.Node("root").Within()
		.Node("user").Within()
			.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").Within()
				.Node("article").Attribute("id", "25").InnerText("Handling DBNulls")
				.Node("article").Attribute("id", "26").InnerText("Accessing my privates")
				.EndWithin()
			.Node("hobbies").Within()
				.Node("hobby").InnerText("Fishing")
				.Node("hobby").InnerText("Photography")
				.Node("hobby").InnerText("Work");

<?xml version="1.0" encoding="utf-8"?>
<root>
	<user>
		<username>orca</username>
		<realname>Mark S. Rasmussen</realname>
		<description>I'll handle any escaping (like &lt; &amp; &gt; for example) needs automagically.</description>
		<articles>
			<article id="25">Handling DBNulls</article>
			<article id="26">Accessing my privates</article>
		</articles>
		<hobbies>
			<hobby>Fishing</hobby>
			<hobby>Photography</hobby>
			<hobby>Work</hobby>
		</hobbies>
	</user>
</root>

Finally, say hello to XmlOutput:

using System.Xml;
using System.Collections.Generic;

public class XmlOutput
{
	// The internal XmlDocument that holds the complete structure.
	XmlDocument xd = new XmlDocument();

	// A stack representing the hierarchy of nodes added. nodeStack.Peek() will always be the current node scope.
	Stack<XmlNode> nodeStack = new Stack<XmlNode>();

	// Whether the next node should be created in the scope of the current node.
	bool nextNodeWithin;

	// The current node. If null, the current node is the XmlDocument itself.
	XmlNode currentNode;

	/// <summary>
	/// Returns the string representation of the XmlDocument.
	/// </summary>
	/// <returns>A string representation of the XmlDocument.</returns>
	public string GetOuterXml()
	{
		return xd.OuterXml;
	}

	/// <summary>
	/// Returns the XmlDocument
	/// </summary>
	/// <returns></returns>
	public XmlDocument GetXmlDocument()
	{
		return xd;
	}

	/// <summary>
	/// Changes the scope to the current node.
	/// </summary>
	/// <returns>this</returns>
	public XmlOutput Within()
	{
		nextNodeWithin = true;

		return this;
	}

	/// <summary>
	/// Changes the scope to the parent node.
	/// </summary>
	/// <returns>this</returns>
	public XmlOutput EndWithin()
	{
		if (nextNodeWithin)
			nextNodeWithin = false;
		else
			nodeStack.Pop();

		return this;
	}

	/// <summary>
	/// Adds an XML declaration with the most common values.
	/// </summary>
	/// <returns>this</returns>
	public XmlOutput XmlDeclaration() { return XmlDeclaration("1.0", "utf-8", ""); }

	/// <summary>
	/// Adds an XML declaration to the document.
	/// </summary>
	/// <param name="version">The version of the XML document.</param>
	/// <param name="encoding">The encoding of the XML document.</param>
	/// <param name="standalone">Whether the document is standalone or not. Can be yes/no/(null || "").</param>
	/// <returns>this</returns>
	public XmlOutput XmlDeclaration(string version, string encoding, string standalone)
	{
		XmlDeclaration xdec = xd.CreateXmlDeclaration(version, encoding, standalone);
		xd.AppendChild(xdec);

		return this;
	}

	/// <summary>
	/// Creates a node. If no nodes have been added before, it'll be the root node, otherwise it'll be appended as a child of the current node.
	/// </summary>
	/// <param name="name">The name of the node to create.</param>
	/// <returns>this</returns>
	public XmlOutput Node(string name)
	{
		XmlNode xn = xd.CreateElement(name);

		// If nodeStack.Count == 0, no nodes have been added, thus the scope is the XmlDocument itself.
		if (nodeStack.Count == 0)
		{
			xd.AppendChild(xn);

			// Automatically change scope to the root DocumentElement.
			nodeStack.Push(xn);
		}
		else
		{
			// If this node should be created within the scope of the current node, change scope to the current node before adding the node to the scope element.
			if (nextNodeWithin)
			{
				nodeStack.Push(currentNode);

				nextNodeWithin = false;
			}

			nodeStack.Peek().AppendChild(xn);
		}

		currentNode = xn;

		return this;
	}

	/// <summary>
	/// Sets the InnerText of the current node without using CData.
	/// </summary>
	/// <param name="text"></param>
	/// <returns></returns>
	public XmlOutput InnerText(string text)
	{
		return InnerText(text, false);
	}

	/// <summary>
	/// Sets the InnerText of the current node.
	/// </summary>
	/// <param name="text">The text to set.</param>
	/// <returns>this</returns>
	public XmlOutput InnerText(string text, bool useCData)
	{
		if (useCData)
			currentNode.AppendChild(xd.CreateCDataSection(text));
		else
			currentNode.AppendChild(xd.CreateTextNode(text));

		return this;
	}

	/// <summary>
	/// Adds an attribute to the current node.
	/// </summary>
	/// <param name="name">The name of the attribute.</param>
	/// <param name="value">The value of the attribute.</param>
	/// <returns>this</returns>
	public XmlOutput Attribute(string name, string value)
	{
		XmlAttribute xa = xd.CreateAttribute(name);
		xa.Value = value;

		currentNode.Attributes.Append(xa);

		return this;
	}
}

Enjoy!

kick it on DotNetKicks.com


Comments

Niels Ladegaard Beck | Oct 24th, 2007, 5:45 PM

Nice! But why not just use LINQ? With the new XML features in .NET 3.5, you can write your last (complex) example like this:

XDocument xd = new XDocument(
new XDeclaration("1.0", "UTF-8", "yes"),
new XElement("root",
new XElement("user",
new XElement("username", "orca"),
new XElement("realname", "Mark S. Rasmussen"),
new XElement("description", "I'll handle any escaping (like < & > for example) needs automagically."),
new XElement("articles",
new XElement("article", new XAttribute("id", "25"), "Handling DBNulls"),
new XElement("article", new XAttribute("id", "26"), "Accessing my privates")),
new XElement("hobbies",
new XElement("hobby", "Fishing"),
new XElement("hobby", "Photography"),
new XElement("hobby", "Work")))));

It gives you the same XML :-)

Or, if you prefer VB.NET (who does?!?):

Dim xd As XDocument = _
<?xml version="1.0" encoding="utf-8"?>
<root>
<user>
<username>orca</username>
<realname>Mark S. Rasmussen</realname>
<description>I'll handle any escaping (like ... for example) needs automagically.</description>
<articles>
<article id="25">Handling DBNulls</article>
<article id="26">Accessing my privates</article>
</articles>
<hobbies>
<hobby>Fishing</hobby>
<hobby>Photography</hobby>
<hobby>Work</hobby>
</hobbies>
</user>
</root>

I've newer used VB.NET before, so I couldn't figure out how to escape the special characters - but I'm sure you know how to do it ;-)

Niels Ladegaard Beck | Oct 24th, 2007, 5:48 PM

When I posted the previous comment, the indentation was correct - it's just this blog that doesn't understand spaces ;-)

Mark S. Rasmussen | Oct 24th, 2007, 6:26 PM

While it is true that LINQ simplifies the syntax, it is - as you say yourself - .NET 3.5 only, in a lot of situations you do not have the luxury to be running 3.5. Furthermore I actually much prefer my fluent syntax over the LINQ syntax (I won't even get into the VB.NET one, yuck), but that is of course of question of personal preference.

Sorry about the spaces, I'll look into it ;)

Matt Berseth | Feb 22nd, 2008, 3:09 PM

Well done. I wish this would have posted this 5 years ago ;)

Chris Pietschmann | Feb 22nd, 2008, 5:26 PM

Very Nice. This is simple, but makes the code so much easier to read. It's definately a step in the right direction.

Andrew | Feb 25th, 2008, 1:29 AM

Is there a particular reason why you didn't just use XmlWriter? It isn't fluent but you could use XmlOutput to wrap it instead of XmlDocument?

The big advantage there is that XmlWriter does the stack management for you:

writer.WriteStartElement("foo");
writer.WriteAttributeString("bar", "baz");
writer.WriteEndElement();

It's also much faster because it streams the Xml directly to the target Stream/TextWriter rather than building the DOM in memory.

Mark S. Rasmussen | Feb 25th, 2008, 1:54 AM

Andrew,

The reason I used the XmlDocument is that I'm often using the XmlOutput class for creating the XmlDocument instance, and then I'll continue working on the instance in the calling code.

Granted, XmlWriter is faster for just spitting out a lot of XML, but it doesn't give the opportunity of retrieving the XmlDocument afterwards. One could create an XmlOutputWriter class that mimics XmlOutput.

Bill Booth | Feb 25th, 2008, 4:21 AM

<snip>
Furthermore I actually much prefer my fluent syntax over the LINQ syntax (I won't even get into the VB.NET one, yuck), but that is of course of question of personal preference.
</snip>

I don't understand this. The only VB I noticed was the XDocument declaration. That is yuck? It looks more like the xml desired than anything on the page.

Mark S. Rasmussen | Feb 25th, 2008, 8:17 AM

Bill,

There's no VB in my code samples at all. I'm talking about the VB specific language feature where you can simply embed XML directly into the source code. It sure makes it easy to write out XML, but I personally do not like mixing in XML markup with the source code.

Cihan Ucar | Feb 25th, 2008, 9:56 AM

Awesome piece of code! It is worth to refactor existing code which produces xml.

Justin Etheredge | Feb 25th, 2008, 8:45 PM

Very nice use of a fluent interface! So simple, yet so powerful. </jealousness>

Jon von Gillern | Feb 25th, 2008, 9:17 PM

I'm not sure if anything could be easier to work with than the XmlSerializer. If you're going to be spitting out or sucking in Xml, you owe it to yourself to look into it.

http://www.vonsharp.net/PutDownTheXmlNodeAndStepAwayFromTheStringBuilder.aspx

Mark S. Rasmussen | Feb 25th, 2008, 9:57 PM

Jon,

I don't want to have to create classes for all the various forms of XML that I might be spitting out. Also, as people mentioned, XmlDocument might not be the best performing - but compared to reflection based serialization, it's blazingly fast.

Now, if I can serialize anonymous classes that I create, that might be a possibility, but it'd still not be nowhere near as concise as the XmlOutput class is.

Bacardi | Feb 27th, 2008, 6:11 AM

Reminds me of jQuery. Very nice. Great work! It's now a part of the collection.

Steve Trefethen | Feb 27th, 2008, 6:22 AM

Thanks for this post, I'm doing a lot of XML right now and this may prove to be a real time saver not to mention making for more readable code.

Ken Egozi | Feb 27th, 2008, 11:34 AM

Very nice and all, nicer API than the default System.XML, but since XML is essentially text, Id use templating solutions for that. See http://www.kenegozi.com/Blog/2008/02/27/generating-xml-do-we-really-another-api.aspx

Sergey Shishkin - Fluent XML Writer | Feb 28th, 2008, 11:46 PM

Pingback

Shawn Oster | Feb 29th, 2008, 4:54 AM

Reminds me a lot of CMarkup over at http://www.firstobject.com/. I actually ported CMarkup way back when it was free from codeproject into Delphi and that's my XML builder of choice these days. I just wrapped your cool fluent interface around CMarkup (in Delphi no less) and I have to say, it's a pleasure to use!

As an aside, who in the world was *ever* using just a StringBuilder to create their markup? Seriously people, you've had XmlWriter since 1.0, how did anyone ever think a SB was a good idea?

James Curran | Mar 3rd, 2008, 11:30 PM

I like the API, except for two minor details.

.Node("root").Within().Node("result")

seems to me to say that <root> is within <result> instead of the other way around. I might suggest "Wraps()".

Next is XmlDeclaration(). It accepts three parameters, all string. I know this matches the XmlDocument method, but it's still dumb. Properly the parameters should be a float, an enum, and a boolean. I might even go for have a overload that accepts a System.Text.Encoding object as it's second parameter.

Kris Vandermotten | Mar 28th, 2008, 10:59 PM

<Jon>I'm not sure if anything could be easier to work with than the XmlSerializer. If you're going to be spitting out or sucking in Xml, you owe it to yourself to look into it.</Jon>

<Mark>I don't want to have to create classes for all the various forms of XML that I might be spitting out. Also, as people mentioned, XmlDocument might not be the best performing - but compared to reflection based serialization, it's blazingly fast.</Mark>

Oh? And of course you know, bacause you've benchmarked it?

Well written Xml serializable classes are allways a lot faster to manipulate than the DOM, also when serializing and deserializing. I know they are, because I did benchmark (and decompiled the generated code).

Sure, on the first run over a small document, the serializer is somewhat slow, because it needs to emit the code that uses the XmlWriter (or XmlReader) to (de)serialize. That's reflection indeed, with Reflection.Emit. For a website, that shouldn't matter at all, but if you don't want to take the hit, use sgen.exe.

Jon is right. Look into it.

And BTW, you might want to look at .ashx files as well.

Mark S. Rasmussen | Mar 29th, 2008, 7:05 PM

Kris,

Actually I didn't "know" per se, I had a hunch. Your comment made me want to test it out:
http://improve.dk/blog/2008/03/29/xmloutput-vs-xmlserializer-performance

XmlOutput is only used to generate Xml, not to read and manipulate it, so that is really not an argument against the XmlOutput class.

I'd very much like to see your own performance results & code to see how you got it to be so fast compared to XmlOutput/XmlDocument.

Oh, and yes, I have "heard" about ASHX files :)

Brandon Morales | Aug 1st, 2008, 7:20 AM

I took some of the suggestions made in the comments, and followed up on your suggestion that your class could be redone with similar functionality using XmlWriter. It still allows for output as XmlDocument though.

Thanks for the wonderful inspiration, your class really made a difference in my Flash development.

Denis Kudriashov | Sep 15th, 2008, 2:12 PM

What you think about this syntax:

Xml xml = new Xml()
xml.With("root", ()=>
{
xml.With("user", ()=>
{
xml
.With("username", "orca")
.With("realname","Mark S. Rasmussen")
.With("description""I'll handle any escaping (like < & > for example) needs automagically.")
.With("articles",()=>
{
xml
.With("article",()=>
{
xml
.WithAttr("id", "25")
.With("Handling DBNulls")
})
.With("article",()=>
{
xml
.WithAttr("id", "26")
.With("Accessing my privates")
});
})
.With("hobbies",()=>
{
xml
.With("hobby","Fishing")
.With("hobby", "Photography")
.With("hobby", "Work");
});
});
});

Moreover, we can replace With() keyword with index []:
xml["user", ()=>
{
xml
["name", "John"]
["address", "Moscow"];
}

In smalltalk language we have more elegant interface:

xml user:
[
xml
name: 'John';
address: 'Moscow';
]

Steve Trefethen | Nov 20th, 2008, 12:52 AM

Wouldn't it make sense to assign currentNode = nodeStack.Pop() in EndsWithin()?

Mark S. Rasmussen | Nov 25th, 2008, 11:10 PM

Hi Steve,

I'm not really sure. As it is now, Within & EndWithin only control stack flow and nothing else. The currentNode variable is what defines what will be modified when we add attributes, inner text. If for instance we went:

Node(A).Within().Node(X).EndsWithin().Attribte("test", "value");

As it is now, the attribute will be put onto the very lastly added node - X. If we change the currentNode value in EndsWithin, the attribute will be added to node A - a node that may be very long away from our current code point, which will kinda mess up the fluentness of the interface.

Also, usually I'll be adding attributes before adding child nodes to a node, thus rendering the issue trivial.

I'm open to arguments :)

/ Mark S. Rasmussen

Steve Trefethen | Nov 26th, 2008, 12:33 AM

Hi Mark,
Thanks for the follow-up. While I can appreciate your example I'd fully expect the Attribute to be added to "A" even though it's "far away". Personally, I'd find it strange to use EndsWithin() then followed by a call to Attributes thinking it will at attributes to a node I just closed out.

I had a case where I wanted to build an XML document inside of a for loop and at the end add attributes to the root node of the document with summary counts. In that case, I made the change I suggested and could then simply add EndWithin() calls to "pop" the currentnode back up to the top of the stack and then call .Attribute().

Anyway, thanks again for the post.

Jason Sun | Dec 15th, 2008, 6:12 AM

I am using your class and I have a shorthand question, currently I have an output like this:
<Feature>
<FCat>Packages</FCat>
<FType>OF</FType>
<FName>
</FName>
<FPrice>0.0</FPrice>
<FDetDesc>
</FDetDesc>
</Feature>

Is there possible that I can change:
<FName>
</FName>
and
<FDetDesc>
</FDetDesc>
to:
<FName /> and
<FDetDesc />
?

Thanks

Jason Sun | Dec 15th, 2008, 7:58 AM

I guess I didn't explain clearly...

this is the simplfied soruce code:

foreach(AutoFeature featureItem in FeatureList) {
xo.Node("Feature").Within();
xo.Node("FCat").InnerText(featureItem.FCat);
xo.Node("FType").InnerText(featureItem.FType);
xo.Node("FName").InnerText(featureItem.FName);
xo.Node("FPrice").InnerText(featureItem.FPrice);
xo.Node("FDetDesc").InnerText(featureItem.FDetDesc);
xo.EndWithin();
}

and as long as any field = null or "" in the InnerText(field), the tag will become

<TAG>
</TAG>

instead of <TAG />

so my quesion is how to change to get shorthand tag?

mark | Jun 6th, 2010, 11:57 AM

Thanks for the follow-up.

auto insurance | Jun 6th, 2010, 11:58 AM

Thanks for this post, I'm doing a lot of XML right now and this may prove to be a real time saver not to mention making for more readable code.

phentermine | Jun 6th, 2010, 12:00 PM

Actually I didn't "know" per se, I had a hunch. Your comment made me want to test it out:
http://improve.dk/blog/2008/03/29/xmloutput-vs-xmlserializer-performance

XmlOutput is only used to generate Xml, not to read and manipulate it, so that is really not an argument against the XmlOutput class.

I'd very much like to see your own performance results & code to see how you got it to be so fast compared to XmlOutput/XmlDocument.

seo expert | Jun 24th, 2010, 2:03 PM

Thanks for this useful post, your given code is easy to understand. I will surly use this code, I have seen first time to use of Xml in any code. Its nice to see this.

office chairs | Jul 4th, 2010, 9:46 AM

This ergonomic high back office chair extends the full length of the back,up to the shoulders and includes support for the head and neck. Our chairsare crafted to perfection and designed to the bodies natural shape, you will find complete comfort with its PU leather material and padded arm rests.

The chair is fitted with optimised functions which include gas height adjustment and tilt mechanism, to allow for greater comfort and allowing you to find your ideal position.

Our executive range of office chairs are built to be Safe, to last for years and cannot be beat in any head to head comparison in its class. Easy assemble, a strong nylon base and 360° swivel, top this PU leather, a fantastic executive look.

high blood pressure supplement | Jul 28th, 2010, 4:15 AM

Thank you very much for putting this site. I've been trying to create a small personal blog recently with photos and stories from my trips. I found some articles about it at the following site about biletul zilei pariuri sportive. My brother also helped a lot with wordpress and stuff. But the most inspiration came from your web-site. Hopefully I will be through with installing it soon and will be able to share some great experience with you! With the best regards.

mineral makeup products | Jul 30th, 2010, 8:04 AM

Thanks for this post, I don't fave so much knowledge about Xml document, even its easy to understand. I will try to use this.

Online security certification | Jul 30th, 2010, 3:18 PM

Thanks for this informative post, with the use of this xml, we can do our work more easily.

Kranik | Aug 5th, 2010, 7:16 AM

Thanks for this useful post, your given code is easy to understand. I will surly use this code, I have seen first time to use of Xml in any code. Its nice to see this.

cheap moving boxes | Aug 6th, 2010, 2:35 PM

Wow its great to see this coding in a very simplest way, with the help of xml coding I will make my work more easier. Thanks.

cheap dave matthews band tickets | Aug 11th, 2010, 2:04 PM

I am hoping the same best work from you in the future as well.

free sign up bonus bingo uk | Aug 20th, 2010, 2:56 AM

Thanks for this podcast. I have had similar experiences when entering the US. When filling out the form i forgot something on the back side, and then when I had corrected my self and came back to the officer he sent me directly to the secondary check. If that was because I forgot the backside, I'm a young adult traveling alone or just a routine I don't know.
At the secondary check the officer was really strict and rude (if I can call it that), but when he saw my Norwegian passport he got all nice and friendly. Then he quickly checked my backpack (not half as thorough as my bag) and sent me off.

cheap international air ticket | Aug 20th, 2010, 12:57 PM

Great post, very useful for me, given XML coding is easy to understand. I will surly use this. Thanks

travel | Aug 24th, 2010, 3:24 PM

Th4t be an epic da shizzi4 post, th4nkie 4it & in da futures we'll be seeing more of it

cruises | Aug 24th, 2010, 3:24 PM

We7ll I8be dat9 ogr6e speekie da speekie, gratz & than4x

flight center | Aug 24th, 2010, 3:25 PM

heb7e sh8at be th34nkie 4it on da posting left & righ8ty

House Cleaning Service | Aug 25th, 2010, 8:26 AM

I liked the post very much. The XML code will definitely help me in future.

free stuf | Aug 25th, 2010, 10:02 AM

It is a simple fluent interface for creating XmlDocuments & strings. Very useful and interesting too.

Prada sunglasses | Aug 30th, 2010, 2:10 PM

After go through this post, I have understand that. with the help of this post I can do so many new things and this post is fill with multiple useful information. Thanks

online bingo | Aug 31st, 2010, 10:56 AM

Mumia is a convicted murderer and his guilt has been AFFIRMED after review by so many Judges learned in the LAW and FACTS and it's people like YOU and other misguided people who cling to a convicted murderer of another human being.

fuel saver devices | Sep 1st, 2010, 12:10 PM

In this given post the use of XML for coding is really interesting and so very easy to understand. Thanks for sharing this informative post.

Add comment

After you have posted a comment, an email will be sent to the provided email address. Before your comment is activated, you will have to click the confirmation link within the email.

Name:

Email (only used for validation):

Website (optional):

Message:

Notify me when new comments are added:

Please type the following letters into the box below:  

Post!