2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 package de.todesbaum.util.xml;
19 import java.util.ArrayList;
20 import java.util.List;
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
24 import javax.xml.parsers.ParserConfigurationException;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NodeList;
30 import org.w3c.dom.Text;
33 * SimpleXML is a helper class to construct XML trees in a fast and simple way.
34 * Construct a new XML tree by calling {@link #SimpleXML(String)} and append new
35 * nodes by calling {@link #append(String)}.
37 * @author David Roden <droden@gmail.com>
38 * @version $Id:SimpleXML.java 221 2006-03-06 14:46:49Z bombe $
40 public class SimpleXML {
43 * A {@link List} containing all child nodes of this node.
45 private List<SimpleXML> children = new ArrayList<SimpleXML>();
48 * The name of this node.
50 private String name = null;
53 * The value of this node.
55 private String value = null;
58 * Constructs a new XML node without a name.
65 * Constructs a new XML node with the specified name.
68 * The name of the new node
70 public SimpleXML(String name) {
75 * Returns the child node of this node with the specified name. If there are
76 * several child nodes with the specified name only the first node is
80 * The name of the child node
81 * @return The child node, or <code>null</code> if there is no child node
82 * with the specified name
84 public SimpleXML getNode(String nodeName) {
85 for (int index = 0, count = children.size(); index < count; index++) {
86 if (children.get(index).name.equals(nodeName)) {
87 return children.get(index);
94 * Returns the child node that is specified by the names. The first element
95 * of <code>nodeNames</code> is the name of the child node of this node, the
96 * second element of <code>nodeNames</code> is the name of a child node's
97 * child node, and so on. By using this method you can descend into an XML
101 * SimpleXML deepNode = topNode.getNodes(new String[] { "person", "address", "number" });
105 * @return A node that is a deep child of this node, or <code>null</code> if
106 * the specified node does not eixst
108 public SimpleXML getNode(String[] nodeNames) {
109 SimpleXML node = this;
110 for (String nodeName: nodeNames) {
111 node = node.getNode(nodeName);
117 * Returns all child nodes of this node.
119 * @return All child nodes of this node
121 public SimpleXML[] getNodes() {
122 return getNodes(null);
126 * Returns all child nodes of this node with the specified name. If there
127 * are no child nodes with the specified name an empty array is returned.
130 * The name of the nodes to retrieve, or <code>null</code> to
132 * @return All child nodes with the specified name
134 public SimpleXML[] getNodes(String nodeName) {
135 List<SimpleXML> resultList = new ArrayList<SimpleXML>();
136 for (SimpleXML child: children) {
137 if ((nodeName == null) || child.name.equals(nodeName)) {
138 resultList.add(child);
141 return resultList.toArray(new SimpleXML[resultList.size()]);
145 * Appends a new XML node with the specified name and returns the new node.
146 * With this method you can create deep structures very fast.
149 * SimpleXML mouseNode = topNode.append("computer").append("bus").append("usb").append("mouse");
153 * The name of the node to append as a child to this node
154 * @return The new node
156 public SimpleXML append(String nodeName) {
157 return append(new SimpleXML(nodeName));
161 * Appends a new XML node with the specified name and value and returns the
165 * The name of the node to append
167 * The value of the node to append
168 * @return The newly appended node
170 public SimpleXML append(String nodeName, String nodeValue) {
171 return append(nodeName).setValue(nodeValue);
175 * Appends the node with all its child nodes to this node and returns the
179 * The node to append as a child
180 * @return The child node that was appended
182 public SimpleXML append(SimpleXML newChild) {
183 children.add(newChild);
187 public void remove(SimpleXML child) {
188 children.remove(child);
191 public void remove(String childName) {
192 SimpleXML child = getNode(childName);
198 public void replace(String childName, String value) {
200 append(childName, value);
203 public void replace(SimpleXML childNode) {
204 remove(childNode.getName());
208 public void removeAll() {
213 * Sets the value of this node.
216 * The new value of this node
219 public SimpleXML setValue(String nodeValue) {
225 * Returns the name of this node.
227 * @return The name of this node
229 public String getName() {
234 * Returns the value of this node.
236 * @return The value of this node
238 public String getValue() {
243 * Returns the value of this node. If the node does not have a value, the
244 * given default value is returned.
247 * The default value to return if the node does not have a value
248 * @return The value of this node
250 public String getValue(String defaultValue) {
251 return (value == null) ? defaultValue : value;
255 * Creates a {@link Document} from this node and all its child nodes.
257 * @return The {@link Document} created from this node
259 public Document getDocument() {
260 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
262 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
263 Document document = documentBuilder.newDocument();
264 Element rootElement = document.createElement(name);
265 document.appendChild(rootElement);
266 addChildren(rootElement);
268 } catch (ParserConfigurationException e) {
274 * Appends all children of this node to the specified {@link Element}. If a
275 * node has a value that is not <code>null</code> the value is appended as a
279 * The element to attach this node's children to
281 private void addChildren(Element rootElement) {
282 for (SimpleXML child: children) {
283 Element childElement = rootElement.getOwnerDocument().createElement(child.name);
284 rootElement.appendChild(childElement);
285 if (child.value != null) {
286 Text childText = rootElement.getOwnerDocument().createTextNode(child.value);
287 childElement.appendChild(childText);
289 child.addChildren(childElement);
295 * Creates a SimpleXML node from the specified {@link Document}. The
296 * SimpleXML node of the document's top-level node is returned.
299 * The {@link Document} to create a SimpleXML node from
300 * @return The SimpleXML node created from the document's top-level node
302 public static SimpleXML fromDocument(Document document) {
303 SimpleXML xmlDocument = new SimpleXML(document.getFirstChild().getNodeName());
304 document.normalizeDocument();
305 return addDocumentChildren(xmlDocument, document.getFirstChild());
309 * Appends the child nodes of the specified {@link Document} to this node.
310 * Text nodes are converted into a node's value.
313 * The SimpleXML node to append the child nodes to
315 * The document whose child nodes to append
316 * @return The SimpleXML node the child nodes were appended to
318 private static SimpleXML addDocumentChildren(SimpleXML xmlDocument, Node document) {
319 NodeList childNodes = document.getChildNodes();
320 for (int childIndex = 0, childCount = childNodes.getLength(); childIndex < childCount; childIndex++) {
321 Node childNode = childNodes.item(childIndex);
322 if ((childNode.getChildNodes().getLength() == 1) && (childNode.getFirstChild().getNodeName().equals("#text")) /*&& (childNode.getFirstChild().getNodeValue().trim().length() != 0)*/) {
323 xmlDocument.append(childNode.getNodeName(), childNode.getFirstChild().getNodeValue());
325 if (!childNode.getNodeName().equals("#text") || (childNode.getChildNodes().getLength() != 0)) {
326 SimpleXML newXML = xmlDocument.append(childNode.getNodeName());
327 addDocumentChildren(newXML, childNode);