/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: XPathQueryTest.java 511423 2007-02-25 03:21:05Z vgritsenko $
*/
package org.apache.xindice.integration.client.services;
import org.apache.xindice.integration.client.AbstractXmlDbClientTest;
import org.apache.xindice.xml.TextWriter;
import org.custommonkey.xmlunit.XMLAssert;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XPathQueryService;
/**
*
* @author <a href="mailto:vladimir@apache.org">Vladimir R. Bossicard</a>
* @author <a href="mailto:kevinoneill@apache.org">Kevin O'Neill</a>
* @version $Revision: 511423 $, $Date: 2007-02-24 22:21:05 -0500 (Sat, 24 Feb 2007) $
*/
public class XPathQueryTest extends AbstractXmlDbClientTest {
private Collection col;
private XPathQueryService xpathservice;
public void setUp() throws Exception {
super.setUp();
this.col = this.client.getCollection(TEST_COLLECTION_PATH);
this.xpathservice = (XPathQueryService) col.getService("XPathQueryService", "1.0");
String document1
= "<?xml version=\"1.0\"?>"
+ "<person>"
+ "<!-- John Smith -->"
+ "<first>John</first>"
+ "<last>Smith</last>"
+ "<age>30</age>"
+ "<phone type=\"work\">555-345-6789</phone>"
+ "</person>";
String document2
= "<?xml version=\"1.0\"?>"
+ "<person>"
+ "<!-- Sally Smith -->"
+ "<first>Sally</first>"
+ "<last>Smith</last>"
+ "<age>20</age>"
+ "<phone type=\"work\">555-345-6789</phone>"
+ "</person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc1", document1);
this.client.insertDocument(TEST_COLLECTION_PATH, "doc2", document2);
}
public void tearDown() throws Exception {
this.client.removeDocument(TEST_COLLECTION_PATH, "doc1");
this.client.removeDocument(TEST_COLLECTION_PATH, "doc2");
super.tearDown();
}
public void testSimpleQuery() throws Exception {
String query = "//person[last='Smith']";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testSimpleAndQuery() throws Exception {
String query = "//person[first='John' and last='Smith']";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
}
public void testSimpleOrQuery() throws Exception {
String query = "//person[first='John' or last='Smith']";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testMultipleOrQuery() throws Exception {
String query = "//person[first='John' or first='Sally' or age]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testAndOrQuery() throws Exception {
String query = "//person[last='Smith' and (first='John' or first='Sally')]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testContainsSearchQuery() throws Exception {
// search all records whose last name contains 'Smi'
String query = "//person[contains(last, 'Smi')]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testStartsWithSearchQuery() throws Exception {
String document3 =
"<?xml version=\"1.0\"?>"
+ "<person>"
+ "<first>Sally</first>"
+ "<last>aSm</last>"
+ "<phone type=\"work\">555-345-6789</phone>"
+ "</person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
// search all records whose last name begins with 'Smi'
String query = "//person[string-length(//person/last) >= 3 and substring(//person/last, 1, 3)='Smi']";
try {
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
} finally {
this.client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
}
public void testEndsWithSearchQuery() throws Exception {
// search all records whose last name begins with 'ith'
String query = "//person[(string-length(//person/last) >= 4) and (substring(//person/last, 2)='mith')]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Document result1 = (Document)((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
assertEquals("person", result1.getDocumentElement().getNodeName());
}
public void testGreaterSearchQuery() throws Exception {
String query = "//person[age > 25]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
}
public void testLesserSearchQuery() throws Exception {
String query = "//person[age < 25]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
Document result0 = (Document)((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals("person", result0.getDocumentElement().getNodeName());
}
public void testNamespaceDOM() throws Exception {
String document3 =
"<?xml version=\"1.0\"?>"
+ "<p:person xmlns:p='http://example.net/person' >"
+ "<p:first>Sally</p:first>"
+ "<p:last>Smith</p:last>"
+ "<p:phone type=\"work\">555-345-6789</p:phone>"
+ "</p:person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
String query = "//h:person[h:first='Sally' and h:last='Smith']/h:first";
xpathservice.setNamespace("h", "http://example.net/person");
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
XMLResource resource = (XMLResource) resultSet.getResource(0);
// ensure that the resource has the correct doc id.
assertEquals("doc3", resource.getDocumentId());
Node node = resource.getContentAsDOM();
// add source node information to the compared xml as it's added by
// the query processor.
XMLAssert.assertXMLEqual("<first xmlns:src='http://xml.apache.org/xindice/Query' src:col='/db/testing/current' src:key='doc3' xmlns='http://example.net/person'>Sally</first>",
TextWriter.toString(node));
this.client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
public void testFetchSingleTextNode() throws Exception {
String query = "//person[first='John' and last='Smith']/first/text()";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1L, resultSet.getSize());
Node result = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals(Node.TEXT_NODE, result.getChildNodes().item(0).getChildNodes().item(0).getNodeType());
assertEquals("John", result.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testFetchMultipleTextNodes() throws Exception {
String query = "//person/first/text()";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals(Node.TEXT_NODE, result0.getChildNodes().item(0).getChildNodes().item(0).getNodeType());
assertEquals(Node.TEXT_NODE, result1.getChildNodes().item(0).getChildNodes().item(0).getNodeType());
assertEquals("John", result0.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
assertEquals("Sally", result1.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testFetchAttributeNode() throws Exception {
String document3 = "<?xml version=\"1.0\"?>" + "<foo bar='foo'>" + "<bar foo='bar' bar='bar'/>" + "</foo>";
client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
try {
String query = "//foo/@bar";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1L, resultSet.getSize());
Node result = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals("foo", result.getChildNodes().item(0).getAttributes().getNamedItem("bar").getNodeValue());
} finally {
client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
}
public void testFetchMultipleAttributeNodes() throws Exception {
String document3 = "<?xml version=\"1.0\"?>" + "<foo bar='foo'>" + "<bar foo='bar' bar='bar'/>" + "</foo>";
client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
try {
String query = "//@bar";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("foo", result0.getChildNodes().item(0).getAttributes().getNamedItem("bar").getNodeValue());
assertEquals("bar", result1.getChildNodes().item(0).getAttributes().getNamedItem("bar").getNodeValue());
} finally {
client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
}
public void testFetchCommentNode() throws Exception {
String query = "//person/comment()[contains(., 'John')]";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
Node result = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
assertEquals(" John Smith ", result.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testFetchMultipleCommentNodes() throws Exception {
String query = "//person/comment()";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals(" John Smith ", result0.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
assertEquals(" Sally Smith ", result1.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testFetchBoolean() throws Exception {
String query = "boolean(//person)";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2L, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("true", result0.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
assertEquals("true", result1.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testFetchString() throws Exception {
String query = "string(//person[first='John' and last='Smith']/first)";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2L, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("John", result0.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
assertEquals(0, result1.getChildNodes().item(0).getChildNodes().getLength());
}
public void testFetchNumber() throws Exception {
String query = "count(//person[first='John' and last='Smith'])";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(2L, resultSet.getSize());
Node result0 = ((XMLResource) resultSet.getResource(0)).getContentAsDOM();
Node result1 = ((XMLResource) resultSet.getResource(1)).getContentAsDOM();
assertEquals("1.0", result0.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
assertEquals("0.0", result1.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());
}
public void testSrcAddedToRootOnly() throws Exception {
String query = "//person[first='John' and last='Smith']";
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
XMLResource resource = (XMLResource) resultSet.getResource(0);
String john
= "<?xml version=\"1.0\"?>"
+ "<person xmlns:src='http://xml.apache.org/xindice/Query' src:col='/db/testing/current' src:key='doc1'>"
+ "<!-- John Smith -->"
+ "<first>John</first>"
+ "<last>Smith</last>"
+ "<age>30</age>"
+ "<phone type=\"work\">555-345-6789</phone>"
+ "</person>";
// ensure that the resource has the correct doc id.
assertEquals("doc1", resource.getDocumentId());
XMLAssert.assertXMLEqual(john, TextWriter.toString(resource.getContentAsDOM()));
}
public void testConflictingPrefix() throws Exception {
String document3 =
"<?xml version=\"1.0\"?>"
+ "<src:person xmlns:src='http://example.net/person' >"
+ "<src:first>Sally</src:first>"
+ "<src:last>Smith</src:last>"
+ "<src:phone type=\"work\">555-345-6789</src:phone>"
+ "</src:person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
String query = "//h:person[h:first='Sally' and h:last='Smith']/h:first";
xpathservice.setNamespace("h", "http://example.net/person");
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
XMLResource resource = (XMLResource) resultSet.getResource(0);
// ensure that the resource has the correct doc id.
assertEquals("doc3", resource.getDocumentId());
Node node = resource.getContentAsDOM();
// add source node information to the compared xml as it's added by
// the query processor.
XMLAssert.assertXMLEqual("<first xmlns:src='http://xml.apache.org/xindice/Query' src:col='/db/testing/current' src:key='doc3' xmlns='http://example.net/person'>Sally</first>",
TextWriter.toString(node));
this.client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
public void testNamespacesNotImportedDeep() throws Exception {
// make sure that we don't have the namespace defs needlessly
// imported from the root all the way through the tree
// i.e. namespaces imported from above root should not
// be spread into child nodes
String document3 =
"<?xml version=\"1.0\"?>"
+ "<p:person xmlns:p='http://example.net/person' >"
+ "<p:first>Sally</p:first>"
+ "<p:last>Smith</p:last>"
+ "<p:phone p:type=\"work\">555-345-6789</p:phone>"
+ "</p:person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
String query = "//h:person[h:first='Sally' and h:last='Smith']";
xpathservice.setNamespace("h", "http://example.net/person");
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
XMLResource resource = (XMLResource) resultSet.getResource(0);
Node node = resource.getContentAsDOM();
String retrieved = TextWriter.toString(node);
assertFalse("Namespace definitions imported deep in: " + retrieved, -1 == retrieved.indexOf("<p:first>"));
// ensure that the resource has the correct doc id.
assertEquals("doc3", resource.getDocumentId());
// add source node information to the compared xml as it's added by
// the query processor. Note, this should work using without the
// prefixes in the control document using the default namespace,
// (i.e. xmlns='http://example.net/person') but I couldn't get it to work
// with XMLAssert (and we'return not testing XMLAssert so we just use the prefixes here too)
XMLAssert.assertXMLEqual("<p:person xmlns:p='http://example.net/person' xmlns:src='http://xml.apache.org/xindice/Query' src:col='/db/testing/current' src:key='doc3'>"
+ "<p:first>Sally</p:first>"
+ "<p:last>Smith</p:last>"
+ "<p:phone p:type=\"work\">555-345-6789</p:phone>"
+ "</p:person>",
TextWriter.toString(node));
this.client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
public void testMathOpQuery() throws Exception {
// force a non-XObject Object to be supplied to evalMathOperation as
// one of its operands
// this works in the buggy version of XPathQueryResolver but only
// because a ClassCastException that cuts short the indexing evaluation
// is caught and ignored forcing a collection scan (if logging WARN, you'll see stack trace)
String query = "//person[substring(last, string-length(last) - two)='ith']";
String document3
= "<?xml version=\"1.0\"?>"
+ "<person>"
+ "<first>Sally</first>"
+ "<last>Smith</last>"
+ "<one>1</one>"
+ "<two>2.0</two>"
+ "<phone call=\"no\" type=\"work\">555-345-6789</phone>"
+ "</person>";
this.client.insertDocument(TEST_COLLECTION_PATH, "doc3", document3);
try {
ResourceSet resultSet = xpathservice.query(query);
assertEquals(1, resultSet.getSize());
} finally {
this.client.removeDocument(TEST_COLLECTION_PATH, "doc3");
}
}
}