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