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
102 * SimpleXML deepNode = topNode.getNodes(new String[] { "person", "address", "number" });
106 * @return A node that is a deep child of this node, or <code>null</code> if
107 * the specified node does not eixst
109 public SimpleXML getNode(String[] nodeNames) {
110 SimpleXML node = this;
111 for (String nodeName : nodeNames) {
112 node = node.getNode(nodeName);
118 * Returns all child nodes of this node.
120 * @return All child nodes of this node
122 public SimpleXML[] getNodes() {
123 return getNodes(null);
127 * Returns all child nodes of this node with the specified name. If there
128 * are no child nodes with the specified name an empty array is returned.
131 * The name of the nodes to retrieve, or <code>null</code> to
133 * @return All child nodes with the specified name
135 public SimpleXML[] getNodes(String nodeName) {
136 List<SimpleXML> resultList = new ArrayList<SimpleXML>();
137 for (SimpleXML child : children) {
138 if ((nodeName == null) || child.name.equals(nodeName)) {
139 resultList.add(child);
142 return resultList.toArray(new SimpleXML[resultList.size()]);
146 * Appends a new XML node with the specified name and returns the new node.
147 * With this method you can create deep structures very fast.
151 * SimpleXML mouseNode = topNode.append("computer").append("bus").append("usb").append("mouse");
155 * The name of the node to append as a child to this node
156 * @return The new node
158 public SimpleXML append(String nodeName) {
159 return append(new SimpleXML(nodeName));
163 * Appends a new XML node with the specified name and value and returns the
167 * The name of the node to append
169 * The value of the node to append
170 * @return The newly appended node
172 public SimpleXML append(String nodeName, String nodeValue) {
173 return append(nodeName).setValue(nodeValue);
177 * Appends the node with all its child nodes to this node and returns the
181 * The node to append as a child
182 * @return The child node that was appended
184 public SimpleXML append(SimpleXML newChild) {
185 children.add(newChild);
189 public void remove(SimpleXML child) {
190 children.remove(child);
193 public void remove(String childName) {
194 SimpleXML child = getNode(childName);
200 public void replace(String childName, String value) {
202 append(childName, value);
205 public void replace(SimpleXML childNode) {
206 remove(childNode.getName());
210 public void removeAll() {
215 * Sets the value of this node.
218 * The new value of this node
221 public SimpleXML setValue(String nodeValue) {
227 * Returns the name of this node.
229 * @return The name of this node
231 public String getName() {
236 * Returns the value of this node.
238 * @return The value of this node
240 public String getValue() {
245 * Returns the value of this node. If the node does not have a value, the
246 * given default value is returned.
249 * The default value to return if the node does not have a value
250 * @return The value of this node
252 public String getValue(String defaultValue) {
253 return (value == null) ? defaultValue : value;
257 * Creates a {@link Document} from this node and all its child nodes.
259 * @return The {@link Document} created from this node
261 public Document getDocument() {
262 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
264 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
265 Document document = documentBuilder.newDocument();
266 Element rootElement = document.createElement(name);
267 document.appendChild(rootElement);
268 addChildren(rootElement);
270 } catch (ParserConfigurationException e) {
276 * Appends all children of this node to the specified {@link Element}. If a
277 * node has a value that is not <code>null</code> the value is appended as a
281 * The element to attach this node's children to
283 private void addChildren(Element rootElement) {
284 for (SimpleXML child : children) {
285 Element childElement = rootElement.getOwnerDocument().createElement(child.name);
286 rootElement.appendChild(childElement);
287 if (child.value != null) {
288 Text childText = rootElement.getOwnerDocument().createTextNode(child.value);
289 childElement.appendChild(childText);
291 child.addChildren(childElement);
297 * Creates a SimpleXML node from the specified {@link Document}. The
298 * SimpleXML node of the document's top-level node is returned.
301 * The {@link Document} to create a SimpleXML node from
302 * @return The SimpleXML node created from the document's top-level node
304 public static SimpleXML fromDocument(Document document) {
305 SimpleXML xmlDocument = new SimpleXML(document.getFirstChild().getNodeName());
306 document.normalizeDocument();
307 return addDocumentChildren(xmlDocument, document.getFirstChild());
311 * Appends the child nodes of the specified {@link Document} to this node.
312 * Text nodes are converted into a node's value.
315 * The SimpleXML node to append the child nodes to
317 * The document whose child nodes to append
318 * @return The SimpleXML node the child nodes were appended to
320 private static SimpleXML addDocumentChildren(SimpleXML xmlDocument, Node document) {
321 NodeList childNodes = document.getChildNodes();
322 for (int childIndex = 0, childCount = childNodes.getLength(); childIndex < childCount; childIndex++) {
323 Node childNode = childNodes.item(childIndex);
324 if ((childNode.getChildNodes().getLength() == 1) && (childNode.getFirstChild().getNodeName().equals("#text")) /*&& (childNode.getFirstChild().getNodeValue().trim().length() != 0)*/) {
325 xmlDocument.append(childNode.getNodeName(), childNode.getFirstChild().getNodeValue());
327 if (!childNode.getNodeName().equals("#text") || (childNode.getChildNodes().getLength() != 0)) {
328 SimpleXML newXML = xmlDocument.append(childNode.getNodeName());
329 addDocumentChildren(newXML, childNode);