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