1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.xmlfield.core.impl.dom;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Map.Entry;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.jaxen.JaxenException;
25 import org.jaxen.XPath;
26 import org.jaxen.dom.DOMXPath;
27 import org.w3c.dom.Node;
28 import org.xmlfield.core.api.XmlFieldNode;
29 import org.xmlfield.core.api.XmlFieldNodeList;
30 import org.xmlfield.core.api.XmlFieldSelector;
31 import org.xmlfield.core.exception.XmlFieldXPathException;
32 import org.xmlfield.core.internal.NamespaceMap;
33
34 import com.google.common.collect.MapMaker;
35
36
37
38
39
40
41
42
43
44 public class DomJaxenSelector implements XmlFieldSelector {
45
46
47
48
49
50
51
52
53 static boolean useCache = false;
54
55 public static XPath addNamespace(final NamespaceMap namespaces, XPath xp)
56 throws JaxenException {
57 if (namespaces != null) {
58 for (Entry<String, String> entry : namespaces) {
59 xp.addNamespace(entry.getKey(), entry.getValue());
60 }
61 }
62 return xp;
63 }
64
65
66
67
68
69 private Map<String, XPath> xpathCache = new MapMaker().softValues()
70 .makeMap();
71
72 private void checkXPathNotNull(String xpath) throws XmlFieldXPathException {
73 if (xpath == null) {
74 throw new XmlFieldXPathException("The requested xpath is null");
75 }
76 }
77
78
79
80
81
82
83
84
85
86
87 private XPath getXPath(NamespaceMap namespaces, String xpath)
88 throws JaxenException {
89 XPath result = null;
90 if (useCache) {
91
92 String key = StringUtils.EMPTY;
93 if (namespaces != null) {
94 key = key + namespaces.toString();
95 }
96 key = key + "|" + xpath;
97
98
99 result = xpathCache.get(key);
100
101
102 if (result == null) {
103 result = new DOMXPath(xpath);
104 addNamespace(namespaces, result);
105 xpathCache.put(key, result);
106 }
107 } else {
108 result = new DOMXPath(xpath);
109 addNamespace(namespaces, result);
110 }
111 return result;
112 }
113
114 @Override
115 public Boolean selectXPathToBoolean(NamespaceMap namespaces, String xpath,
116 XmlFieldNode node) throws XmlFieldXPathException {
117 checkXPathNotNull(xpath);
118 final Boolean value;
119 try {
120 final XPath xp = getXPath(namespaces, xpath);
121 value = xp.booleanValueOf(node.getNode());
122 } catch (JaxenException e) {
123 throw new XmlFieldXPathException(e);
124 }
125 return value;
126 }
127
128 @Override
129 public XmlFieldNode selectXPathToNode(NamespaceMap namespaces,
130 String xpath, XmlFieldNode node) throws XmlFieldXPathException {
131 checkXPathNotNull(xpath);
132 final Node value;
133 try {
134 final XPath xp = getXPath(namespaces, xpath);
135 value = (Node) xp.selectSingleNode(node.getNode());
136 } catch (JaxenException e) {
137 throw new XmlFieldXPathException(e);
138 }
139 if (value == null) {
140 return null;
141 }
142 return new DomNode(value);
143 }
144
145 @SuppressWarnings("unchecked")
146 @Override
147 public XmlFieldNodeList selectXPathToNodeList(NamespaceMap namespaces,
148 String xpath, XmlFieldNode node) throws XmlFieldXPathException {
149 checkXPathNotNull(xpath);
150 final List<Node> values;
151 try {
152 final XPath xp = getXPath(namespaces, xpath);
153 values = xp.selectNodes(node.getNode());
154 } catch (JaxenException e) {
155 throw new XmlFieldXPathException(e);
156 }
157 final int nodeCount = values.size();
158
159 final List<XmlFieldNode> list = new ArrayList<XmlFieldNode>();
160
161 for (int i = 0; i < nodeCount; ++i) {
162
163 final XmlFieldNode subNode = new DomNode(values.get(i));
164
165 list.add(subNode);
166 }
167 return new DomNodeList(list);
168 }
169
170 @Override
171 public Double selectXPathToNumber(NamespaceMap namespaces, String xpath,
172 XmlFieldNode node) throws XmlFieldXPathException {
173 checkXPathNotNull(xpath);
174 final Double value;
175 try {
176 final XPath xp = getXPath(namespaces, xpath);
177 value = xp.numberValueOf(node.getNode()).doubleValue();
178 } catch (JaxenException e) {
179 throw new XmlFieldXPathException(e);
180 }
181 return value;
182 }
183
184 @Override
185 public String selectXPathToString(NamespaceMap namespaces, String xpath,
186 XmlFieldNode node) throws XmlFieldXPathException {
187 checkXPathNotNull(xpath);
188 final String value;
189 try {
190 final XPath xp = getXPath(namespaces, xpath);
191 value = xp.stringValueOf(node.getNode());
192 } catch (JaxenException e) {
193 throw new XmlFieldXPathException(e);
194 }
195 return value;
196 }
197
198 }