2 * jSite - SimpleXML.java - Copyright © 2006–2012 David Roden
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 package de.todesbaum.util.xml;
21 import java.util.ArrayList;
22 import java.util.List;
24 import javax.xml.parsers.DocumentBuilder;
25 import javax.xml.parsers.DocumentBuilderFactory;
26 import javax.xml.parsers.ParserConfigurationException;
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32 import org.w3c.dom.Text;
35 * SimpleXML is a helper class to construct XML trees in a fast and simple way.
36 * Construct a new XML tree by calling {@link #SimpleXML(String)} and append new
37 * nodes by calling {@link #append(String)}.
39 * @author David Roden <droden@gmail.com>
40 * @version $Id:SimpleXML.java 221 2006-03-06 14:46:49Z bombe $
42 public class SimpleXML {
45 * A {@link List} containing all child nodes of this node.
47 private List<SimpleXML> children = new ArrayList<SimpleXML>();
50 * The name of this node.
52 private String name = null;
55 * The value of this node.
57 private String value = null;
60 * Constructs a new XML node without a name.
67 * Constructs a new XML node with the specified name.
70 * The name of the new node
72 public SimpleXML(String name) {
77 * Returns the child node of this node with the specified name. If there are
78 * several child nodes with the specified name only the first node is
82 * The name of the child node
83 * @return The child node, or <code>null</code> if there is no child node
84 * with the specified name
86 public SimpleXML getNode(String nodeName) {
87 for (int index = 0, count = children.size(); index < count; index++) {
88 if (children.get(index).name.equals(nodeName)) {
89 return children.get(index);
96 * Returns the child node that is specified by the names. The first element
97 * of <code>nodeNames</code> is the name of the child node of this node, the
98 * second element of <code>nodeNames</code> is the name of a child node's
99 * child node, and so on. By using this method you can descend into an XML
104 * SimpleXML deepNode = topNode.getNodes(new String[] { "person", "address", "number" });
108 * @return A node that is a deep child of this node, or <code>null</code> if
109 * the specified node does not eixst
111 public SimpleXML getNode(String[] nodeNames) {
112 SimpleXML node = this;
113 for (String nodeName : nodeNames) {
114 node = node.getNode(nodeName);
120 * Returns all child nodes of this node.
122 * @return All child nodes of this node
124 public SimpleXML[] getNodes() {
125 return getNodes(null);
129 * Returns all child nodes of this node with the specified name. If there
130 * are no child nodes with the specified name an empty array is returned.
133 * The name of the nodes to retrieve, or <code>null</code> to
135 * @return All child nodes with the specified name
137 public SimpleXML[] getNodes(String nodeName) {
138 List<SimpleXML> resultList = new ArrayList<SimpleXML>();
139 for (SimpleXML child : children) {
140 if ((nodeName == null) || child.name.equals(nodeName)) {
141 resultList.add(child);
144 return resultList.toArray(new SimpleXML[resultList.size()]);
148 * Appends a new XML node with the specified name and returns the new node.
149 * With this method you can create deep structures very fast.
153 * SimpleXML mouseNode = topNode.append("computer").append("bus").append("usb").append("mouse");
157 * The name of the node to append as a child to this node
158 * @return The new node
160 public SimpleXML append(String nodeName) {
161 return append(new SimpleXML(nodeName));
165 * Appends a new XML node with the specified name and value and returns the
169 * The name of the node to append
171 * The value of the node to append
172 * @return The newly appended node
174 public SimpleXML append(String nodeName, String nodeValue) {
175 return append(nodeName).setValue(nodeValue);
179 * Appends the node with all its child nodes to this node and returns the
183 * The node to append as a child
184 * @return The child node that was appended
186 public SimpleXML append(SimpleXML newChild) {
187 children.add(newChild);
191 public void remove(SimpleXML child) {
192 children.remove(child);
195 public void remove(String childName) {
196 SimpleXML child = getNode(childName);
202 public void replace(String childName, String value) {
204 append(childName, value);
207 public void replace(SimpleXML childNode) {
208 remove(childNode.getName());
212 public void removeAll() {
217 * Sets the value of this node.
220 * The new value of this node
223 public SimpleXML setValue(String nodeValue) {
229 * Returns the name of this node.
231 * @return The name of this node
233 public String getName() {
238 * Returns the value of this node.
240 * @return The value of this node
242 public String getValue() {
247 * Returns the value of this node. If the node does not have a value, the
248 * given default value is returned.
251 * The default value to return if the node does not have a value
252 * @return The value of this node
254 public String getValue(String defaultValue) {
255 return (value == null) ? defaultValue : value;
259 * Creates a {@link Document} from this node and all its child nodes.
261 * @return The {@link Document} created from this node
263 public Document getDocument() {
264 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
266 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
267 Document document = documentBuilder.newDocument();
268 Element rootElement = document.createElement(name);
269 document.appendChild(rootElement);
270 addChildren(rootElement);
272 } catch (ParserConfigurationException e) {
278 * Appends all children of this node to the specified {@link Element}. If a
279 * node has a value that is not <code>null</code> the value is appended as a
283 * The element to attach this node's children to
285 private void addChildren(Element rootElement) {
286 for (SimpleXML child : children) {
287 Element childElement = rootElement.getOwnerDocument().createElement(child.name);
288 rootElement.appendChild(childElement);
289 if (child.value != null) {
290 Text childText = rootElement.getOwnerDocument().createTextNode(child.value);
291 childElement.appendChild(childText);
293 child.addChildren(childElement);
299 * Creates a SimpleXML node from the specified {@link Document}. The
300 * SimpleXML node of the document's top-level node is returned.
303 * The {@link Document} to create a SimpleXML node from
304 * @return The SimpleXML node created from the document's top-level node
306 public static SimpleXML fromDocument(Document document) {
307 SimpleXML xmlDocument = new SimpleXML(document.getFirstChild().getNodeName());
308 document.normalizeDocument();
309 return addDocumentChildren(xmlDocument, document.getFirstChild());
313 * Appends the child nodes of the specified {@link Document} to this node.
314 * Text nodes are converted into a node's value.
317 * The SimpleXML node to append the child nodes to
319 * The document whose child nodes to append
320 * @return The SimpleXML node the child nodes were appended to
322 private static SimpleXML addDocumentChildren(SimpleXML xmlDocument, Node document) {
323 NodeList childNodes = document.getChildNodes();
324 for (int childIndex = 0, childCount = childNodes.getLength(); childIndex < childCount; childIndex++) {
325 Node childNode = childNodes.item(childIndex);
326 if ((childNode.getChildNodes().getLength() == 1) && (childNode.getFirstChild().getNodeName().equals("#text"))) {
327 xmlDocument.append(childNode.getNodeName(), childNode.getFirstChild().getNodeValue());
329 if (!childNode.getNodeName().equals("#text") || (childNode.getChildNodes().getLength() != 0)) {
330 SimpleXML newXML = xmlDocument.append(childNode.getNodeName());
331 addDocumentChildren(newXML, childNode);