1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 package org.jaxen;
64
65 import junit.framework.TestCase;
66
67 import java.io.File;
68 import java.util.ArrayList;
69 import java.util.Iterator;
70 import java.util.List;
71 import java.util.Stack;
72
73 import javax.xml.parsers.DocumentBuilder;
74 import javax.xml.parsers.DocumentBuilderFactory;
75 import javax.xml.parsers.ParserConfigurationException;
76
77 import org.jaxen.function.StringFunction;
78 import org.jaxen.saxpath.helpers.XPathReaderFactory;
79 import org.w3c.dom.Attr;
80 import org.w3c.dom.Document;
81 import org.w3c.dom.Element;
82 import org.w3c.dom.NamedNodeMap;
83 import org.w3c.dom.Node;
84 import org.w3c.dom.NodeList;
85
86 public abstract class XPathTestBase extends TestCase
87 {
88 protected static String VAR_URI = "http://jaxen.org/test-harness/var";
89 protected static String TESTS_XML = "xml/test/tests.xml";
90
91 protected static boolean verbose = true;
92
93 private DocumentBuilder builder;
94 private ContextSupport contextSupport;
95
96 private Stack executionContext = new Stack();
97
98 public XPathTestBase(String name)
99 {
100 super( name );
101 }
102
103 public void setUp() throws ParserConfigurationException
104 {
105 this.contextSupport = null;
106 System.setProperty( XPathReaderFactory.DRIVER_PROPERTY,
107 "" );
108 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
109 factory.setNamespaceAware(true);
110 builder = factory.newDocumentBuilder();
111
112 }
113
114 public void log(String text)
115 {
116 log( verbose,
117 text );
118 }
119
120 public void log(boolean actualVerbose,
121 String text)
122 {
123 if ( ! actualVerbose )
124 {
125 return;
126 }
127
128 System.out.println( text );
129 }
130
131 public void testXPaths() throws Exception
132 {
133 log( "Loading test file: " + TESTS_XML );
134
135 File f = new File( TESTS_XML);
136 Document doc = builder.parse( f );
137
138 NodeList documents = doc.getElementsByTagName("document");
139 for (int i = 0; i < documents.getLength(); i++)
140 {
141 Element eachDocElem = (Element) documents.item(i);
142 testDocument( eachDocElem );
143 }
144 }
145
146 protected void testDocument(Element docElem) throws Exception
147 {
148 String url = docElem.getAttribute( "url" );
149
150 Object testDoc = getDocument( url );
151
152 log( "-----------------------------" );
153 log( "Document [" + url + "]" );
154
155 this.executionContext.push( url );
156
157 NodeList contexts = docElem.getElementsByTagName( "context" );
158
159 for (int i = 0; i < contexts.getLength(); i++)
160 {
161 Element context = (Element) contexts.item(i);
162
163 testContext( testDoc,
164 context );
165 }
166
167 this.executionContext.pop();
168
169 log( "-----------------------------" );
170 }
171
172 protected void testContext(Object testDoc,
173 Element contextElem) throws Exception
174 {
175 setupNamespaceContext( contextElem );
176 setupVariableContext( contextElem );
177
178 String xpathStr = contextElem.getAttribute( "select" );
179
180 log( "Initial Context :: " + xpathStr );
181
182 this.executionContext.push( xpathStr );
183
184 BaseXPath xpath = new BaseXPath( xpathStr );
185
186 List list = xpath.selectNodes( getContext( testDoc ) );
187
188 Iterator iter = list.iterator();
189 Object contextNode = null;
190
191 while ( iter.hasNext() )
192 {
193 contextNode = iter.next();
194 runTests( contextElem, contextNode );
195 }
196
197 this.executionContext.pop();
198 }
199
200 protected void runTests(Element contextElem,
201 Object context) throws Exception
202 {
203 NodeList countTests = contextElem.getElementsByTagName( "test" );
204
205 for (int i = 0; i < countTests.getLength(); i++)
206 {
207 Element test = (Element) countTests.item(i);
208 runTest( context, test );
209 }
210
211 NodeList valueOfs = contextElem.getChildNodes();
212
213 for (int i = 0; i < valueOfs.getLength(); i++)
214 {
215 Node node = valueOfs.item(i);
216 if (node.getNodeType() == Node.ELEMENT_NODE) {
217 Element valueOf = (Element) valueOfs.item(i);
218 if (valueOf.getNodeName().equals("valueOf")) {
219 testValueOf( context, valueOf );
220 }
221 }
222 }
223 }
224
225 protected void runTest(Object context,
226 Element test) throws Exception
227 {
228 String xpathStr = test.getAttribute( "select" );
229 String debugStr = test.getAttribute( "debug" );
230 boolean debug = verbose;
231
232 if ( ! "".equals(debugStr) )
233 {
234 if ( "true".equals( debugStr ) || "on".equals( debugStr ) )
235 {
236 debug = true;
237 }
238 }
239
240 log( debug, " Select :: " + xpathStr );
241
242 this.executionContext.push( xpathStr );
243
244 String count = test.getAttribute( "count" );
245 String exception = test.getAttribute( "exception" );
246
247 try
248 {
249 BaseXPath xpath = new BaseXPath( xpathStr );
250 List results = xpath.selectNodes( getContext( context ) );
251 if ( ! "".equals(count) )
252 {
253 int expectedSize = Integer.parseInt( count );
254 log ( debug,
255 " Expected Size :: " + expectedSize );
256 log ( debug,
257 " Result Size :: " + results.size() );
258
259 if ( expectedSize != results.size() )
260 {
261 log ( debug,
262 " ## FAILED" );
263 log ( debug,
264 " ## xpath: " + xpath + " = " + xpath.debug() );
265
266 Iterator resultIter = results.iterator();
267
268 while ( resultIter.hasNext() )
269 {
270 log ( debug,
271 " --> " + resultIter.next() );
272 }
273 }
274 assertEquals( this.executionContext.toString(),
275 expectedSize,
276 results.size() );
277
278 if (exception !=null && (exception.equals("on") || exception.equals("true"))) {
279 fail("An exception was expected.");
280 }
281
282 }
283
284
285 NodeList valueOfs = test.getElementsByTagName("valueOf");
286 for (int i = 0; i < valueOfs.getLength(); i++) {
287 Element valueOf = (Element) valueOfs.item(i);
288 testValueOf( results.get(0), valueOf);
289 }
290
291 }
292 catch (UnsupportedAxisException e)
293 {
294 log ( debug,
295 " ## SKIPPED -- Unsupported Axis" );
296 }
297 catch (JaxenException e) {
298
299 if (exception.equals("on") || exception.equals("true")) {
300 log (debug, " Caught expected exception "+e.getMessage());
301 }
302 else throw e;
303 }
304
305 this.executionContext.pop();
306 }
307
308 protected void testValueOf(Object context,
309 Element valueOf) throws Exception
310 {
311 String xpathStr = valueOf.getAttribute( "select" );
312 String debugStr = valueOf.getAttribute( "debug" );
313 boolean debug = verbose;
314
315 if ( ! "".equals(debugStr) )
316 {
317 if ( "true".equals( debugStr )
318 ||
319 "on".equals( debugStr ) )
320 {
321 debug = true;
322 }
323 }
324
325 BaseXPath xpath = new BaseXPath( xpathStr );
326
327 this.executionContext.push( xpathStr );
328
329 try
330 {
331 Object node = xpath.evaluate( getContext( context ) );
332
333 String expected = getFullText(valueOf);
334 String result = StringFunction.evaluate( node,
335 getNavigator() );
336
337 log ( debug,
338 " Select :: " + xpathStr );
339 log ( debug,
340 " Expected :: " + expected );
341 log ( debug,
342 " Result :: " + result );
343
344 if ( ! expected.equals( result ) )
345 {
346 log ( debug,
347 " ## FAILED" );
348 log ( debug,
349 " ## xpath: " + xpath + " = " + xpath.debug() );
350 }
351
352 assertEquals( this.executionContext.toString(),
353 expected,
354 result );
355 }
356 catch (UnsupportedAxisException e)
357 {
358 log ( debug,
359 " ## SKIPPED -- Unsupported Axis " );
360
361 }
362
363 this.executionContext.pop();
364 }
365
366 protected Context getContext(Object contextNode)
367 {
368 Context context = new Context( getContextSupport() );
369
370 List list = new ArrayList( 1 );
371 list.add( contextNode );
372 context.setNodeSet( list );
373
374 return context;
375 }
376
377 public ContextSupport getContextSupport()
378 {
379 if ( this.contextSupport == null )
380 {
381 this.contextSupport = new ContextSupport( new SimpleNamespaceContext(),
382 XPathFunctionContext.getInstance(),
383 new SimpleVariableContext(),
384 getNavigator() );
385 }
386
387 return this.contextSupport;
388 }
389
390 public abstract Navigator getNavigator();
391
392 public abstract Object getDocument(String url) throws Exception;
393
394 private void setupNamespaceContext(Element contextElem)
395 {
396 SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
397
398 NamedNodeMap attributes = contextElem.getAttributes();
399
400 for (int i = 0; i < attributes.getLength(); i++ )
401 {
402 Attr attr = (Attr) attributes.item(i);
403 if ("http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) {
404
405 String prefix = attr.getLocalName();
406 String uri = attr.getNodeValue();
407
408 nsContext.addNamespace( prefix, uri );
409
410 System.out.println( " ---> " + prefix + " == " + uri );
411 }
412 }
413
414 getContextSupport().setNamespaceContext( nsContext );
415 }
416
417 private void setupVariableContext(Element contextElem)
418 {
419 SimpleVariableContext varContext = new SimpleVariableContext();
420
421 NamedNodeMap varIter = contextElem.getAttributes();
422
423 for (int i = 0; i < varIter.getLength(); i++ )
424 {
425 Attr eachVar = (Attr) varIter.item(i);
426
427 if ( VAR_URI.equals(eachVar.getNamespaceURI()) )
428 {
429 String varName = eachVar.getLocalName();
430 String varValue = eachVar.getNodeValue();
431
432 varContext.setVariableValue( null,
433 varName,
434 varValue );
435 }
436 }
437
438 getContextSupport().setVariableContext( varContext );
439 }
440
441 private static String getFullText(Node node) {
442 StringBuffer result = new StringBuffer(12);
443 NodeList children = node.getChildNodes();
444 for (int i = 0; i < children.getLength(); i++) {
445 Node child = children.item(i);
446 int type = child.getNodeType();
447 if (type == Node.TEXT_NODE) {
448 result.append(child.getNodeValue());
449 }
450 else if (type == Node.CDATA_SECTION_NODE) {
451 result.append(child.getNodeValue());
452 }
453 else if (type == Node.ELEMENT_NODE) {
454 result.append(getFullText(child));
455 }
456 else if (type == Node.ENTITY_REFERENCE_NODE) {
457 result.append(getFullText(child));
458 }
459 }
460 return result.toString();
461 }
462
463 }