The goal was to write a simple fluent and recursive tag builder.
Simple – means the implementation should be as short as possible.
Fluent – means a fluent interface
Recursive – means that tags could possibly be nested one inside the other.
The implementation is as follows:
public class TagBuilder
{
public TagBuilder() { }
public TagBuilder( string TagName, TagBuilder Parent )
{
this.tagName = TagName;
this.parent = Parent;
}
private string tagName;
private TagBuilder parent;
private StringBuilder body = new StringBuilder();
private Dictionary<string, string> _attributes = new Dictionary<string, string>();
public TagBuilder AddContent( string Content )
{
body.Append( Content );
return this;
}
public TagBuilder AddContentFormat( string Format, params object[] args )
{
body.AppendFormat( Format, args );
return this;
}
public TagBuilder StartTag( string TagName )
{
TagBuilder tag = new TagBuilder( TagName, this );
return tag;
}
public TagBuilder EndTag()
{
parent.AddContent( this.ToString() );
return parent;
}
public TagBuilder AddAttribute( string Name, string Value )
{
_attributes.Add( Name, Value );
return this;
}
public override string ToString()
{
StringBuilder tag = new StringBuilder();
// preamble
if ( !string.IsNullOrEmpty( this.tagName ) )
tag.AppendFormat( "<{0}", tagName );
if ( _attributes.Count > 0 )
{
tag.Append( " " );
tag.Append(
string.Join( " ",
_attributes
.Select(
kvp => string.Format( "{0}='{1}'", kvp.Key, kvp.Value ) )
.ToArray() ) );
}
// body/ending
if ( body.Length > 0 )
{
if ( !string.IsNullOrEmpty( this.tagName) || this._attributes.Count > 0 )
tag.Append( ">" );
tag.Append( body.ToString() );
if ( !string.IsNullOrEmpty( this.tagName ) )
tag.AppendFormat( "</{0}>", this.tagName );
}
else
if ( !string.IsNullOrEmpty( this.tagName ) )
tag.Append( "/>" );
return tag.ToString();
}
}
Example usage:
var script =
tag.StartTag( "parent" )
.AddAttribute( "parentproperty1", "true" )
.AddAttribute( "parentproperty2", "5" )
.StartTag( "child1")
.AddAttribute( "childproperty1", "c" )
.AddContent( "childbody" )
.EndTag()
.StartTag( "child2" )
.AddAttribute( "childproperty2", "c" )
.AddContent( "childbody" )
.EndTag()
.EndTag()
.StartTag( "script" )
.AddContent( "$.scriptbody();")
.EndTag()
.ToString();
Note that I can nest the hierarchy plus I can have two or more tags one beside the other (siblings). The output of this example call is:
<parent parentproperty1='true' parentproperty2='5'><child1 childproperty1='c'>ch
ildbody</child1><child2 childproperty2='c'>childbody</child2></parent><script>$.
scriptbody();</script>
Feel free to modify the code. An example extension would be to implement indentation.
4 comments:
how can you produce the following data with the code:
<a>x<b>y</b>x</a>
@liuhongbo: sure you can:
var _example =
tag.StartTag( "a" )
.AddContent( "x" )
.StartTag( "b" )
.AddContent( "y" )
.EndTag()
.AddContent( "x" )
.EndTag()
.ToString();
Great class. Very intuitive way of building HTML on the server side. Thanks for sharing
Post a Comment