1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.exorcist.midgard;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
24 import javax.xml.parsers.ParserConfigurationException;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerConfigurationException;
27 import javax.xml.transform.TransformerException;
28 import javax.xml.transform.TransformerFactory;
29 import javax.xml.transform.dom.DOMSource;
30 import javax.xml.transform.stream.StreamResult;
31
32 import org.w3c.dom.Document;
33 import org.w3c.dom.Element;
34
35 /***
36 * Document builder class. This class provides an intuitive
37 * interface for incrementally building DOM documents.
38 */
39 public final class DOMBuilder {
40
41 /*** Static factory for creating DOM DocumentBuilder instances. */
42 private static final DocumentBuilderFactory BUILDER_FACTORY =
43 DocumentBuilderFactory.newInstance();
44
45 /*** Static factory for creating document to output stream transformers. */
46 private static final TransformerFactory TRANSFORMER_FACTORY =
47 TransformerFactory.newInstance();
48
49 /*** The DOM document being built by this builder. */
50 private final Document document;
51
52 private final String namespace;
53 private final String prefix;
54
55 /*** The current element. */
56 private Element current;
57
58 /***
59 * Creates a builder for a new DOM document. A new DOM document is
60 * instantiated and initialized to contain a root element with the given
61 * name. The root element is set as the current element of this builder.
62 *
63 * @param name name of the root element
64 * @throws ParserConfigurationException if a document cannot be created
65 */
66 public DOMBuilder(String name, String namespace, String prefix)
67 throws ParserConfigurationException {
68 DocumentBuilder builder = BUILDER_FACTORY.newDocumentBuilder();
69 document = builder.newDocument();
70 current = document.createElementNS(namespace, prefix + ":" + name);
71 current.setAttribute("xmlns:" + prefix, namespace);
72 document.appendChild(current);
73 this.namespace = namespace;
74 this.prefix = prefix;
75 }
76
77
78 /***
79 * Writes the document built by this builder into the given output stream.
80 * This method is normally invoked only when the document is fully built.
81 *
82 * @param xml XML output stream
83 * @throws IOException if the document could not be written
84 */
85 public void write(OutputStream xml) throws IOException {
86 try {
87 Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
88 transformer.transform(
89 new DOMSource(document), new StreamResult(xml));
90 } catch (TransformerConfigurationException e) {
91 throw new IOException(e.getMessage());
92 } catch (TransformerException e) {
93 throw new IOException(e.getMessage());
94 }
95 }
96
97 /***
98 * Creates a new element with the given name as the child of the
99 * current element and makes the created element current. The
100 * {@link #endElement() endElement} method needs to be called
101 * to return back to the original element.
102 *
103 * @param name name of the new element
104 */
105 public void startElement(String name) {
106 Element element = document.createElementNS(namespace, prefix + ":" + name);
107 current.appendChild(element);
108 current = element;
109 }
110
111 /***
112 * Makes the parent element current. This method should be invoked
113 * after a child element created with the
114 * {@link #startElement(String) startElement} method has been fully
115 * built.
116 */
117 public void endElement() {
118 current = (Element) current.getParentNode();
119 }
120
121 /***
122 * Sets the named attribute of the current element.
123 *
124 * @param name attribute name
125 * @param value attribute value
126 */
127 public void setAttribute(String name, String value) {
128 current.setAttribute(name, value);
129 }
130
131 /***
132 * Sets the named boolean attribute of the current element.
133 *
134 * @param name attribute name
135 * @param value boolean attribute value
136 */
137 public void setAttribute(String name, boolean value) {
138 setAttribute(name, String.valueOf(value));
139 }
140
141 /***
142 * Adds the given string as text content to the current element.
143 *
144 * @param content text content
145 */
146 public void addContent(String content) {
147 current.appendChild(document.createTextNode(content));
148 }
149
150 /***
151 * Adds a new child element with the given name and text content.
152 * The created element will contain no attributes and no child elements
153 * of its own.
154 *
155 * @param name child element name
156 * @param content child element content
157 */
158 public void addContentElement(String name, String content) {
159 startElement(name);
160 addContent(content);
161 endElement();
162 }
163
164 }