/** * XMLNodeAsXQueryParameterTest.java * * 2005 by O2 IT Engineering * Zurich, Switzerland (CH) */ package org.exist.xquery; import org.exist.test.ExistXmldbEmbeddedServer; import org.exist.xmldb.XmldbURI; import org.junit.ClassRule; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xmldb.api.base.ResourceSet; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.XMLResource; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import static org.junit.Assert.fail; /** * Class to test eXist's capability to handle XML Nodes as XQuery parameter. * * @author Tobias Wunden * @version 1.0 */ public class XMLNodeAsXQueryParameterTest { @ClassRule public final static ExistXmldbEmbeddedServer existEmbeddedServer = new ExistXmldbEmbeddedServer(false, true); /** * This test passes a W3C dom node as an xquery parameter to eXist and tries * to read it back in: * <ul> * <li>Register a database instance</li> * <li>Write a document to the database using the XQueryService</li> * <li>Read the document from the database using XmlDB</li> * <li>Check for the document content</li> * </ul> */ @Test public final void xmlNodeAsXQueryParameter() throws XMLDBException, ParserConfigurationException, IOException, SAXException, IllegalAccessException, InstantiationException, ClassNotFoundException { final String document = "test.xml"; // create document final String xmlDocument = "<XmlNodeTest/>"; // write document to the database store(xmlDocument, document); // add content using XUpdate final String xmlData = "<content/>"; try(final Reader reader = new StringReader(xmlData)) { final InputSource is = new InputSource(reader); final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); final Document doc = docBuilder.parse(is); xupdate(doc.getFirstChild()); // read document back from database final Node root = load(document); if (root == null) { fail("Document " + document + " was not found in the database!"); } // issue xpath query final Node node = root.getFirstChild(); if (node == null) { fail("XUpdate:append using w3c dom node failed! Content node was not returned."); } } } /** * Stores the given xml fragment into the database. * * @param xml the xml document * @param document the document name * @throws XMLDBException on database error */ private void store(final String xml, final String document) throws XMLDBException { final StringBuilder query = new StringBuilder(); query.append("xquery version \"1.0\";"); query.append("declare namespace xmldb=\"http://exist-db.org/xquery/xmldb\";"); query.append("declare variable $local:document external;"); query.append("declare variable $local:data external;"); query.append("let $loggedIn := xmldb:login(\"" + XmldbURI.ROOT_COLLECTION + "\", \"admin\", \"\"),"); query.append("$doc := xmldb:store(\"" + XmldbURI.ROOT_COLLECTION + "\", $local:document, $local:data)"); query.append("return <result/>"); final Map<String, Object> externalVariables = new HashMap<>(); externalVariables.put("local:document", document); externalVariables.put("local:data", xml); existEmbeddedServer.executeQuery(query.toString(), externalVariables); } /** * Updates the given xml fragment in the database using XUpdate. * * @param data the data node * @throws XMLDBException on database error */ private void xupdate(final Object data) throws XMLDBException { if (data == null) { fail("Cannot update because data is 'null'"); } final StringBuilder query = new StringBuilder(); query.append("xquery version \"1.0\";"); query.append("declare namespace xmldb=\"http://exist-db.org/xquery/xmldb\";"); query.append("declare variable $local:data external;"); query.append("declare variable $xupdate {"); query.append("<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">"); query.append("<xu:append select=\"xmldb:xcollection('" + XmldbURI.ROOT_COLLECTION + "')/XmlNodeTest\">"); query.append("{$local:data}"); query.append("</xu:append>"); query.append("</xu:modifications>"); query.append("};"); query.append("let $isLoggedIn := xmldb:login('" + XmldbURI.ROOT_COLLECTION + "', \"admin\", \"\"),"); query.append("$mods := xmldb:update(\"" + XmldbURI.ROOT_COLLECTION + "\", $xupdate)"); query.append("return <modifications>{$mods}</modifications>"); final Map<String, Object> externalVariables = new HashMap<>(); externalVariables.put("local:data", data); existEmbeddedServer.executeQuery(query.toString(), externalVariables); } /** * Loads the xml document identified by <code>document</code> from the database. * * @param document the document to load * @throws XMLDBException on database error */ private Node load(final String document) throws XMLDBException { final StringBuilder query = new StringBuilder(); query.append("xquery version \"1.0\";"); query.append("declare variable $local:document external;"); query.append("let $survey := xmldb:document(string-join(('" + XmldbURI.ROOT_COLLECTION + "', $local:document), '/'))"); query.append("return $survey"); final Map<String, Object> externalVariables = new HashMap<>(); externalVariables.put("local:document", document); final ResourceSet results = existEmbeddedServer.executeQuery(query.toString(), externalVariables); if (results != null && results.getSize() > 0) { return ((XMLResource)results.getIterator().nextResource()).getContentAsDOM(); } return null; } }