Class MarkupBuilder<T>
- Type Parameters:
T
- This should always be parameterized with the exact same class that is extending theMarkupBuilder
to support fluent style.
- Direct Known Subclasses:
GeneratedHtmlBuilder
Writer
.
Description
Writes XML markup to aWriter
.
The Builder part of the name is somewhat misleading as
this class does not store or keep track of all the markup objects created but rather
writes using the writer as soon as it can.
Thus the order of operations performed on this class is very important and should
follow the order that you would write the markup.
Usage
You should not use this class directly but rather one of its subclasses that is parameterized with itself (see Extending). You generally define the markup you want to write using Java anonymous classes that extend either aMarkupBuilder
or MarkupWriter
.
Markup builders write immediately to a writer where as a markup writer
writes when told to. But again in both cases you generally define the markup with an anonymous class.
For examples of use its best to see Html
for an XHTML builder which will write XHTML
markup immediatly or HtmlWriter
which allows you to define XHTML markup then write it later.
Markup writers
are more useful for MVC frameworks and builders
are more for convenience.
Extending
If you would you would like to make your own builder you should subclass this class or a subclass that has generic parameter (<T>).The custom builder should be parameterized to itself to support fluent style.
Example:
public class MyMarkup extends MarkupBuilder<MyMarkup> { public MyMarkup(Writer builder) { super(builder); } protected MyMarkup getSelf() { return this; } public MyMarkup myTag() { return start("myTag"); } }
Composition
Besides the extending method above you can achieve composition of markup builders by using MarkupWriter's instead. SeeMarkupWriter
. Writing tags and attributes
Seestart(String)
and end()
for writing tags.
See attr(String...)
for writting attributes.
Variable expansion
Simple named variable replacements are supported through the${...}notation. See
bind(String, Object)
, and text(String)
.
Pretty Printing aka Indenting
See #indentIndenter
. For most cases you can use SimpleIndenter
Namespaces
You can either manually maintain namespaces and namespace prefixes by setting the correct attributes and then writing tags with the namespace prefix. Example:start("prefix:tagName")
.
Or you can use the namespace methods: ns()
, ns(String)
, xmlns(String, String)
The following Nested builders are very helpful for working with multiple XML schemas.
Nested builders
Nested builders are an easy way to allow different markup styles to coexist elegantly. An example might be HTML with in XSL. You would have an HTML builder nested inside the XSL builder.Example:
new Xslt(writer) {{ ns("xsl"); template().match("stuff"); new Html(writer) {{ html().body().done(); }} done(); }}See
MarkupBuilder(MarkupBuilder)
.
Thread safety
This class and subclasses are not thread safe. One way to make a builder thread safe is to synchronize on the passed in writer:synchronize(writer) { new SomeBuilder(writer) {{ }}; }
Efficiency and Validation
To keep the builder efficient and elegant there is very little XML validation. There is no guarantee that the markup generated will always be well formed. GenerallyText
will be escaped appropriately.
For those seriously concerned with performance an appropriate implementation of
Writer
should be given to the builder.
For example: In a single threaded environment where you are writing to memory
Commons IO StringBuilderWriter
is a good choice over StringWriter
.
On the other hand if you are writing very large XML document to a file
or network socket PrintWriter
is probably a better choice.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class
static enum
Policy for how tags should be closed. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate int
private Indenter
protected static Indenter
An indenter that turns off indenting.protected static Indenter
A default indenter that uses tabs.protected static Indenter
Indents by keeping a tag pair on the same line.private String
private MarkupBuilder
<?> private Indenter
private static final String
private Stack
<MarkupBuilder.Tag> private Writer
-
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
Use for deferred writer.MarkupBuilder
(MarkupBuilder<?> builder) Create a nested builder from given builder.MarkupBuilder
(MarkupBuilder<?> builder, boolean nested) Create a nested builder from a builder or resume from a builder.MarkupBuilder
(Writer writer) Create a builder using the given writer. -
Method Summary
Modifier and TypeMethodDescriptionfinal T
Adds attributes to the laststart tag
.final T
Binds a named variables to be used for expansion inattributes
andtext
.final T
bind
(Collection<Map.Entry<String, Object>> nvps) Convenience forbind(String, Object)
private void
final void
done()
Call when completely done with the builder.final T
end()
Closes the laststart tag
.final T
end
(int i) Closes the inputed number of open tags.final T
endAll()
Closes all open tags.protected String
The strategy for escaping attribute markup.protected String
The strategy for escaping element markup.protected String
escapeMarkup
(String raw) Deprecated.private String
protected abstract T
getSelf()
Needed for fluent style and Java parameterization limitations.Sets the indenter.final T
ns()
Restores the current namespace prefix to whatever the surrounding tags prefix is.final T
Sets the current namespace prefix.private String
final T
Write text with out escaping or variable expansion.final T
Writes text with out escaping.final void
setDepth
(int depth) Sets the indent depth after the builder has been created.final void
Sets the writer after the builder has been created.final T
Starts a tag using the default closing policyMarkupBuilder.TagClosingPolicy.NORMAL
.final T
start
(String tag, MarkupBuilder.TagClosingPolicy policy) Starts a tag but does not immediately write it till the next tag is started.final T
Writes variable expanded escaped text inside a tag.final T
Removes a binding.final T
write
(MarkupWriter... writers) Writes immediately by passing the writer to eachMarkupWriter
in the order passed in.private void
private void
private void
writeAttributes
(Map<String, String> attrs) private void
private void
private void
private void
private void
final T
Sets the default namespace on the last started tag.final T
Sets an XML namespace.
-
Field Details
-
tagStack
-
writer
-
attributes
-
bindings
-
previousBuilder
-
depth
private int depth -
namespacePrefix
-
previousIndenter
-
indenter
-
q
- See Also:
-
indentOn
A default indenter that uses tabs. -
indentOff
An indenter that turns off indenting. -
indentSameLine
Indents by keeping a tag pair on the same line.
-
-
Constructor Details
-
MarkupBuilder
Create a builder using the given writer.- Parameters:
writer
- nevernull
.
-
MarkupBuilder
Create a nested builder from given builder. Make suredone()
is called when finished with the nested builder so that the parent builder can resume using the writer.- Parameters:
builder
- parent builder, nevernull
.- See Also:
-
MarkupBuilder
protected MarkupBuilder()Use for deferred writer. The writer should beset
before the builder is used.- See Also:
-
MarkupBuilder
Create a nested builder from a builder or resume from a builder.- Parameters:
builder
- nevernull
.nested
-true
means nested,false
means resuming.
-
-
Method Details
-
getSelf
Needed for fluent style and Java parameterization limitations. Almost all public methods should return whatever this method returns.Most implementations only have to do:
return this;
- Returns:
- the current builder which is usually
this
object.
-
ns
Restores the current namespace prefix to whatever the surrounding tags prefix is. To set the namespace to the default namespace call:ns(null);
- Returns:
- maybe
null
. - See Also:
-
ns
Sets the current namespace prefix. If a tag is started when the prefix is set to a non-null non-empty string, the prefix will be added in front of the tag.Example:
ns("html").div().end();
Result:<html:div></html:div>
- Parameters:
prefix
- maybenull
- Returns:
- this, not
null
.
-
setWriter
Sets the writer after the builder has been created. Only useful with the empty constructor.- Parameters:
writer
- nevernull
- Throws:
IllegalArgumentException
- if the writer has already been set or the given writer is null.
-
setDepth
public final void setDepth(int depth) Sets the indent depth after the builder has been created. Only useful with the empty constructor.- Parameters:
depth
- should greater than or equal0
-
indent
Sets the indenter.- Parameters:
indenter
- ifnull
reverts to the previous builder.- Returns:
- the builder.
- See Also:
-
getAttributes
-
text
Writes variable expanded escaped text inside a tag.- Parameters:
text
- the text will be escaped and variables will be expanded.- Returns:
- never
null
. - See Also:
-
raw
Write text with out escaping or variable expansion.- Parameters:
text
-- Returns:
- never
null
. - See Also:
-
raw
Writes text with out escaping.- Parameters:
text
-expand
-true
does variable expansion.- Returns:
- never
null
.
-
bind
Binds a named variables to be used for expansion inattributes
andtext
. Variables are represented with by${...}
.Example
bind("name", "Ferris"); text("${name}");
Variables are expanded in order and can be referred in a later binding.
bind("firstName", "Adam"); bind("lastName", "Gent"); bind("fullName", "${firstName} ${lastName}");
- Parameters:
name
- nevernull
or empty.value
- maybenull
.- Returns:
- never
null
.
-
unbind
Removes a binding. There is no failure if the binding does not exist.- Parameters:
name
- maybenull
.- Returns:
- never
null
. - See Also:
-
bind
Convenience forbind(String, Object)
- Parameters:
nvps
- nevernull
.- Returns:
- never
null
.
-
start
Starts a tag using the default closing policyMarkupBuilder.TagClosingPolicy.NORMAL
.Equivalent to:
start("tag", TagClosingPolicy.NORMAL)
.- Parameters:
tag
-- Returns:
- this, never
null
. - See Also:
-
start
Starts a tag but does not immediately write it till the next tag is started. TheMarkupBuilder.TagClosingPolicy
dictates whether or not the tag needs to beclosed
. Thusend()
does not need to be called for all tags.- Parameters:
tag
- nevernull
or empty.policy
- nevernull
.- Returns:
- never
null
. - See Also:
-
attr
- Parameters:
attrs
- name value pairs. Its invalid for an odd number of arguments.- Returns:
- never
null
. - Throws:
IllegalArgumentException
- odd number of arguments.
-
xmlns
Sets the default namespace on the last started tag.- Parameters:
uri
- ifnull
nothing will happen.- Returns:
- this, never
null
. - See Also:
-
xmlns
Sets an XML namespace.- Parameters:
uri
- ifnull
nothing will happen.prefix
- ifnull
or blank will act like the default namespace and no prefix.- Returns:
- this, never
null
.
-
end
Closes the inputed number of open tags.- Parameters:
i
- less than zero will do nothing.- Returns:
- never
null
. - See Also:
-
end
Closes the laststart tag
. This is equivalent to</tag> or <tag/> depending on the
MarkupBuilder.TagClosingPolicy
.- Returns:
- never
null
. - See Also:
-
endAll
Closes all open tags.- Returns:
- never
null
. - See Also:
-
done
public final void done()Call when completely done with the builder. This is required for nested builders.If a builder is used again after
done()
is called an exception (usuallyIllegalArgumentException
) will be thrown. -
write
Writes immediately by passing the writer to eachMarkupWriter
in the order passed in.- Parameters:
writers
- nevernull
, null elements passed in are ignored.- Returns:
- never
null
. - Since:
- 0.2.2
-
writeCurrentTag
private void writeCurrentTag() -
writeStartTag
-
writeTag
-
writeEndTag
-
writeAttributes
-
writeAttr
-
q
-
expand
-
write
-
checkWriter
private void checkWriter() -
createMap
-
escapeMarkup
Deprecated.Please useescapeElementMarkup(String)
andescapeAttributeMarkup(String)
DEPRECATED.- Parameters:
raw
- maybenull
.- Returns:
- maybe
null
if null for input. - See Also:
-
escapeElementMarkup
The strategy for escaping element markup. The default is escape for XML.- Parameters:
raw
- maybenull
.- Returns:
- maybe
null
if null for input. - See Also:
-
escapeAttributeMarkup
The strategy for escaping attribute markup. The default escaping is XML. Entities will be used for white space characters:#xD, #xA, #x9
CR, newline, and tab, respectively.
- Parameters:
raw
- maybenull
.- Returns:
- maybe
null
if null for input.
-
writeIndent
-
escapeElementMarkup(String)
andescapeAttributeMarkup(String)