1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.devyant.decorutils.xml;
17
18 import com.sun.org.apache.xpath.internal.XPathAPI;
19 import org.w3c.dom.Document;
20 import org.w3c.dom.NamedNodeMap;
21 import org.w3c.dom.Node;
22 import org.w3c.dom.NodeList;
23 import org.xml.sax.InputSource;
24 import org.xml.sax.SAXException;
25
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.ParserConfigurationException;
29 import javax.xml.transform.TransformerException;
30 import java.io.IOException;
31 import java.util.Collection;
32 import java.util.LinkedList;
33
34 /***
35 * A simple wrapper for XML documents. Each {@link DynaNode} has a set of
36 * attributes which include text data retrieved from child nodes body.
37 *
38 * @author Filipe Tavares
39 * @version $Revision 1.0$ ($Author: ftavares$)
40 * @since 31/Jan/2005 14:22:19
41 */
42 public class SimpleXmlWrapper {
43 /***
44 * The XML document to wrap.
45 */
46 private Document doc;
47
48 /***
49 * Creates a new <code>SimpleXmlWrapper</code> instance.
50 * @param file The XML file
51 * @throws ParserConfigurationException Thrown by document factory
52 * @throws IOException Thrown by XML parser
53 * @throws SAXException Thrown by XML parser
54 */
55 public SimpleXmlWrapper(final String file)
56 throws ParserConfigurationException, IOException, SAXException {
57
58 DocumentBuilderFactory factory =
59 DocumentBuilderFactory.newInstance();
60 DocumentBuilder builder =
61 factory.newDocumentBuilder();
62 InputSource is = new InputSource(file);
63 doc = builder.parse(is);
64 }
65
66 /***
67 * Returns a <code>Collection</code> of the nodes
68 * selected by the XPath query.
69 * @param xpath XPath query
70 * @return <code>Collection</code> of <code>DynaNode</code>'s
71 * @throws TransformerException Thrown by the XPath API
72 */
73 public final Collection getNodes(final String xpath)
74 throws TransformerException {
75
76 NodeList nodes = XPathAPI.selectNodeList(doc, xpath);
77 return convert(null, nodes);
78 }
79
80 /***
81 * Returns a <code>Collection</code> of all the nodes in the document.
82 * @return <code>Collection</code> of <code>DynaNode</code>'s
83 * @throws TransformerException Thrown by the XPath API
84 */
85 public final Collection getNodes() throws TransformerException {
86
87
88
89
90 NodeList nodes = doc.getChildNodes();
91
92 return convert(null, nodes);
93 }
94
95 /***
96 * Converts the <code>NodeList</code> instance to a <code>Collection</code>
97 * of <code>DynaNode</code>'s.
98 * @param bean The parent node
99 * @param nodes The child nodes
100 * @return <code>Collection</code> of <code>DynaNode</code>'s
101 */
102 private static Collection convert(final DynaNode bean,
103 final NodeList nodes) {
104 LinkedList list = new LinkedList();
105
106 for (int i = 0; i < nodes.getLength(); i++) {
107 final Node node = nodes.item(i);
108 if (node.getNodeType() == Node.ELEMENT_NODE) {
109 DynaNode child = getDynaNode(bean, node);
110 list.add(child);
111 } else if ((node.getNodeType() == Node.TEXT_NODE)
112 && (bean != null)
113 && (bean.getParent() != null)
114 && (!node.getNodeValue().matches("^//s$"))) {
115 bean.getParent()
116 .set(bean.getName(), node.getNodeValue().trim());
117 }
118 }
119
120 if (list.isEmpty()) {
121 return null;
122 } else {
123 return list;
124 }
125 }
126
127 /***
128 * Create a <code>DynaNode</code>.
129 * @param parent The parent node
130 * @param node The node
131 * @return A <code>DynaNode</code> instance
132 */
133 private static DynaNode getDynaNode(final DynaNode parent,
134 final Node node) {
135 DynaNode bean = new DynaNode();
136 bean.setName(node.getNodeName());
137 bean.setParent(parent);
138
139 if (node.hasAttributes()) {
140 NamedNodeMap nodeList = node.getAttributes();
141
142 for (int i = 0; i < nodeList.getLength(); i++) {
143 bean.set(nodeList.item(i).getNodeName(),
144 nodeList.item(i).getNodeValue());
145 }
146 }
147
148 if (node.hasChildNodes()) {
149 bean.setChildren(convert(bean, node.getChildNodes()));
150 }
151
152 return bean;
153 }
154 }