Para consultar el repositorio, podemos usar el estándar XPathQueryService
o la clase XQueryService
de eXist . La API XML: DB define diferentes tipos de servicios, que pueden ser proporcionados o no por la base de datos. El método getService
de clase Collection
llama a un servicio si está disponible. El método espera que el nombre del servicio sea el primer parámetro, y su versión (como una cadena) como el segundo.
El siguiente es un ejemplo del uso de XML: DB API para ejecutar una consulta de base de datos:
El siguiente ejemplo ejecuta una consulta XPath que se pasa al programa como parámetro.
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
import org.exist.xmldb.EXistResource;
public class XPathExample {
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
/**
* args[0] Should be the name of the collection to access
* args[1] Should be the XPath expression to execute
*/
public static void main(String args[]) throws Exception {
final String driver = "org.exist.xmldb.DatabaseImpl";
// initialize database driver
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
try {
col = DatabaseManager.getCollection(URI + args[0]);
XPathQueryService xpqs = (XPathQueryService)col.getService("XPathQueryService", "1.0");
xpqs.setProperty("indent", "yes");
ResourceSet result = xpqs.query(args[1]);
ResourceIterator i = result.getIterator();
Resource res = null;
while(i.hasMoreResources()) {
try {
res = i.nextResource();
System.out.println(res.getContent());
} finally {
//dont forget to cleanup resources
try { ((EXistResource)res).freeResources(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
} finally {
//dont forget to cleanup
if(col != null) {
try { col.close(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
}
}
Para ejecutar la consulta, se llama al método service.query
(xpath). Este método devuelve un ResourceSet
, que contiene los recursos encontrados por la consulta. ResourceSet.getIterator ()
nos da un iterador sobre estos recursos. Cada recurso contiene un único fragmento o valor de documento, seleccionado por la expresión XPath.
Internamente, eXist no distingue entre expresiones XPath y XQuery. Por lo tanto, XQueryService se asigna a la misma clase de implementación que XPathQueryService. Sin embargo, proporciona algunos métodos adicionales. Lo más importante es que cuando se habla con una base de datos integrada, XQueryService permite que la expresión XQuery se compile en una representación interna, que luego se puede reutilizar. Con la compilación, el código de ejemplo anterior se vería como sigue:
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
import org.exist.xmldb.EXistResource;
public class XQueryExample {
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
/**
* args[0] Should be the name of the collection to access
* args[1] Should be the XQuery to execute
*/
public static void main(String args[]) throws Exception {
final String driver = "org.exist.xmldb.DatabaseImpl";
// initialize database driver
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
try {
col = DatabaseManager.getCollection(URI + args[0]);
XQueryService xqs = (XQueryService) col.getService("XQueryService", "1.0");
xqs.setProperty("indent", "yes");
CompiledExpression compiled = xqs.compile(args[1]);
ResourceSet result = xqs.execute(compiled);
ResourceIterator i = result.getIterator();
Resource res = null;
while(i.hasMoreResources()) {
try {
res = i.nextResource();
System.out.println(res.getContent());
} finally {
//dont forget to cleanup resources
try { ((EXistResource)res).freeResources(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
} finally {
//dont forget to cleanup
if(col != null) {
try { col.close(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
}
}
El servidor XML-RPC almacena automáticamente en la memoria caché las expresiones compiladas, por lo que la compilación a través del controlador remoto no produce ningún efecto si la expresión ya está almacenada en la memoria caché.
A continuación, nos gustaría almacenar un nuevo documento en el repositorio. Esto se hace creando un nuevo XMLResource, asignándole el contenido del nuevo documento y llamando al método storeResource de la clase Colección.
Primero, un nuevo recurso es creado por el método Collection.createResource ()
, y espera dos parámetros: el id y el tipo de recurso que se crea. Si el parámetro id es nulo, se generará automáticamente una identificación de recurso única.
En algunos casos, es posible que la colección aún no exista, por lo que debemos crearla. Para crear una nueva colección, llame al método createCollection
del servicio CollectionManagementService
. En el siguiente ejemplo, simplemente comenzamos en el objeto de colección raíz para obtener el servicio CollectionManagementService
.
import java.io.File;
import org.exist.xmldb.EXistResource;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
public class StoreExample {
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
/**
* args[0] Should be the name of the collection to access
* args[1] Should be the name of the file to read and store in the collection
*/
public static void main(String args[]) throws Exception {
if(args.length < 2) {
System.out.println("usage: StoreExample collection-path document");
System.exit(1);
}
final String driver = "org.exist.xmldb.DatabaseImpl";
// initialize database driver
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
XMLResource res = null;
try {
col = getOrCreateCollection(args[0]);
// create new XMLResource; an id will be assigned to the new resource
res = (XMLResource)col.createResource(null, "XMLResource");
File f = new File(args[1]);
if(!f.canRead()) {
System.out.println("cannot read file " + args[1]);
return;
}
res.setContent(f);
System.out.print("storing document " + res.getId() + "...");
col.storeResource(res);
System.out.println("ok.");
} finally {
//dont forget to cleanup
if(res != null) {
try { ((EXistResource)res).freeResources(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
if(col != null) {
try { col.close(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
}
private static Collection getOrCreateCollection(String collectionUri) throws
XMLDBException {
return getOrCreateCollection(collectionUri, 0);
}
private static Collection getOrCreateCollection(String collectionUri, int pathSegmentOffset) throws XMLDBException {
Collection col = DatabaseManager.getCollection(URI + collectionUri);
if(col == null) {
if(collectionUri.startsWith("/")) {
collectionUri = collectionUri.substring(1);
}
String pathSegments[] = collectionUri.split("/");
if(pathSegments.length > 0) {
StringBuilder path = new StringBuilder();
for(int i = 0; i <= pathSegmentOffset; i++) {
path.append("/" + pathSegments[i]);
}
Collection start = DatabaseManager.getCollection(URI + path);
if(start == null) {
//collection does not exist, so create
String parentPath = path.substring(0, path.lastIndexOf("/"));
Collection parent = DatabaseManager.getCollection(URI + parentPath);
CollectionManagementService mgt = (CollectionManagementService) parent.getService("CollectionManagementService", "1.0");
col = mgt.createCollection(pathSegments[pathSegmentOffset]);
col.close();
parent.close();
} else {
start.close();
}
}
return getOrCreateCollection(collectionUri, ++pathSegmentOffset);
} else {
return col;
}
}
}
El método XMLResource.setContent ()
carga el objeto Java como que se pasa como parámetro. El controlador eXist comprueba si el objeto es un archivo. De lo contrario, el objeto se transforma en una cadena llamando al método toString ()
del objeto. Pasar un archivo tiene una gran ventaja: si la base de datos se ejecuta en modo incrustado, el archivo se pasará directamente al indexador. De esta forma, el contenido del archivo no tiene que cargarse en la memoria. Esto es útil si los archivos son muy grandes.