1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.xml.transformer;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.context.MuleContextAware;
15 import org.mule.api.expression.ExpressionRuntimeException;
16 import org.mule.api.lifecycle.InitialisationException;
17 import org.mule.api.registry.RegistrationException;
18 import org.mule.api.transformer.TransformerException;
19 import org.mule.config.i18n.CoreMessages;
20 import org.mule.config.i18n.MessageFactory;
21 import org.mule.module.xml.util.NamespaceManager;
22 import org.mule.transformer.AbstractTransformer;
23 import org.mule.transformer.types.DataTypeFactory;
24
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.Map;
30
31 import javax.xml.namespace.NamespaceContext;
32 import javax.xml.namespace.QName;
33 import javax.xml.xpath.XPath;
34 import javax.xml.xpath.XPathConstants;
35 import javax.xml.xpath.XPathExpressionException;
36 import javax.xml.xpath.XPathFactory;
37
38 import org.xml.sax.InputSource;
39
40
41
42
43
44
45
46 public class XPathExtractor extends AbstractTransformer implements MuleContextAware
47 {
48
49
50
51 public enum ResultType
52 {
53 NODESET,
54 NODE,
55 STRING,
56 BOOLEAN,
57 NUMBER
58 }
59
60 private volatile XPath xpath = XPathFactory.newInstance().newXPath();
61 private volatile Map<String, String> prefixToNamespaceMap = null;
62 private volatile String expression;
63 private volatile ResultType resultType = ResultType.STRING;
64 private NamespaceManager namespaceManager;
65
66 public XPathExtractor()
67 {
68 registerSourceType(DataTypeFactory.create(org.w3c.dom.Node.class));
69 registerSourceType(DataTypeFactory.create(InputSource.class));
70 }
71
72 @Override
73 public void setMuleContext(MuleContext context)
74 {
75 this.muleContext = context;
76 try
77 {
78 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
79 }
80 catch (RegistrationException e)
81 {
82 throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
83 }
84 }
85
86 @Override
87 public void initialise() throws InitialisationException
88 {
89 super.initialise();
90
91 if (expression == null)
92 {
93 throw new InitialisationException(
94 MessageFactory.createStaticMessage("An expression must be supplied to the StandardXPathExtractor"),
95 this);
96 }
97
98 if (namespaceManager != null)
99 {
100 if (prefixToNamespaceMap == null)
101 {
102 prefixToNamespaceMap = new HashMap<String, String>(namespaceManager.getNamespaces());
103 }
104 else
105 {
106 prefixToNamespaceMap.putAll(namespaceManager.getNamespaces());
107 }
108 }
109
110 getXpath().setNamespaceContext(new NamespaceContext()
111 {
112 @Override
113 public String getNamespaceURI(String prefix)
114 {
115 return prefixToNamespaceMap.get(prefix);
116 }
117
118 @Override
119 public String getPrefix(String namespaceURI)
120 {
121
122 for (Map.Entry<String, String> entry : prefixToNamespaceMap.entrySet())
123 {
124 if (namespaceURI.equals(entry.getValue()))
125 {
126 return entry.getKey();
127 }
128 }
129
130 return null;
131 }
132
133 @Override
134 public Iterator<?> getPrefixes(String namespaceURI)
135 {
136 String prefix = getPrefix(namespaceURI);
137 if (prefix == null)
138 {
139 return Collections.emptyList().iterator();
140 }
141 else
142 {
143 return Arrays.asList(prefix).iterator();
144 }
145 }
146 });
147 }
148
149 @Override
150 public Object doTransform(Object src, String encoding) throws TransformerException
151 {
152 QName resultType;
153 switch (getResultType())
154 {
155 case BOOLEAN :
156 resultType = XPathConstants.BOOLEAN;
157 break;
158 case NODE :
159 resultType = XPathConstants.NODE;
160 break;
161 case NODESET :
162 resultType = XPathConstants.NODESET;
163 break;
164 case NUMBER :
165 resultType = XPathConstants.NUMBER;
166 break;
167 default :
168 resultType = XPathConstants.STRING;
169 break;
170 }
171
172 try
173 {
174 if (src instanceof InputSource)
175 {
176 return xpath.evaluate(expression, (InputSource) src, resultType);
177 }
178 else
179 {
180 return xpath.evaluate(expression, src, resultType);
181 }
182 }
183 catch (XPathExpressionException e)
184 {
185 throw new TransformerException(this, e);
186 }
187 }
188
189
190
191
192 public String getExpression()
193 {
194 return expression;
195 }
196
197
198
199
200 public void setExpression(String expression)
201 {
202 this.expression = expression;
203 }
204
205
206
207
208
209
210 public ResultType getResultType()
211 {
212 return resultType;
213 }
214
215
216
217
218
219
220 public void setResultType(ResultType resultType)
221 {
222 this.resultType = resultType;
223 }
224
225
226
227
228
229
230 public XPath getXpath()
231 {
232 return xpath;
233 }
234
235
236
237
238
239
240 public void setXpath(XPath xPath)
241 {
242 this.xpath = xPath;
243 }
244
245
246
247
248
249
250 public Map<String, String> getNamespaces()
251 {
252 return prefixToNamespaceMap;
253 }
254
255
256
257
258
259
260 public void setNamespaces(Map<String, String> prefixToNamespaceMap)
261 {
262 this.prefixToNamespaceMap = prefixToNamespaceMap;
263 }
264 }