Hi. I've found a strange behaviour with the xquery "replace node" command. It seems that new namespace declarations within the XML tree added are not taken into account. Please, find hereafter a JUnit test code.
Laurent
package com.cyim.basex.test.ns;
import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test;
import org.basex.server.ClientSession; import org.basex.util.Util;
/** * Test support of XML namespaces. * * @author Laurent Chevalier l.chevalier@cyim.com */ public final class NamespaceTest { /** Client session. */ private ClientSession session;
/** Database name. */ protected static final String DB = Util.name(NamespaceTest.class);
/** * Opens a client session, creates a database and loads documents. * @throws java.io.IOException IO exception */ @Before public void setUp() throws java.io.IOException { session = new ClientSession("localhost", 1984, "admin", "admin"); session.execute(String.format("create db %s <default/>", DB));
// Loads documents. addDoc("doc/1"); addDoc("doc/2"); addDoc("doc/3"); }
/** * Adds a document. * @param uri * @throws java.io.IOException */ private void addDoc(String uri) throws java.io.IOException { // Document content. java.lang.StringBuilder qs = new java.lang.StringBuilder(); qs.append("<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C" xmlns:core="http://rdfs.cyim.com/CoreContent#%5C%22%3E%5Cn"); qs.append(String.format(" <core:Container rdf:about="%s"/>\n", uri)); qs.append("</rdf:RDF>");
// Adds it. java.io.InputStream in = new java.io.ByteArrayInputStream(qs.toString().getBytes("UTF-8")); try { session.add(uri, in); } finally { in.close(); } }
/** * Drops the database and close remaining client sessions. * @throws java.io.IOException IO exception */ @After public void tearDown() throws java.io.IOException { session.execute("drop db " + DB); session.close(); }
/** * Inserts a node. * * @param uri Document uri. * @throws java.io.IOException IO exception */ private void insertNode(String uri) throws java.io.IOException { java.lang.StringBuilder qs = new java.lang.StringBuilder("xquery\n"); qs.append("declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C%22;%5Cn"); qs.append("declare namespace core = "http://rdfs.cyim.com/CoreContent#%5C%22;%5Cn"); qs.append("declare namespace wfdata = "http://rdfs.cyim.com/WorkflowData#%5C%22;%5Cn"); qs.append("insert node ") .append("<wfdata:Workflow xmlns:wfdata="http://rdfs.cyim.com/WorkflowData#%5C%22%3E%5Cn") .append(" wfdata:raiseOn2011-11-01T11:34:08Z</wfdata:raiseOn>\n") .append("</wfdata:Workflow>\n") .append("into /rdf:RDF/*[@rdf:about="" + uri + ""] "); session.execute(qs.toString()); }
/** * Replaces a node and declares the 'wfdata' prefix on the 'core:Container' node. * * @param uri Document uri. * @throws java.io.IOException IO exception */ private void replaceNode(String uri) throws java.io.IOException { java.lang.StringBuilder qs = new java.lang.StringBuilder("xquery\n"); qs.append("declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C%22;%5Cn"); qs.append("declare namespace core = "http://rdfs.cyim.com/CoreContent#%5C%22;%5Cn"); qs.append("declare namespace wfdata = "http://rdfs.cyim.com/WorkflowData#%5C%22;%5Cn"); qs.append("replace node /rdf:RDF/*[@rdf:about="" + uri + ""] with <core:Container rdf:about="" + uri + "" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C" xmlns:core="http://rdfs.cyim.com/CoreContent#%5C" xmlns:wfdata="http://rdfs.cyim.com/WorkflowData#%5C%22%3E%5Cn") .append(" wfdata:Workflow\n") .append(" wfdata:raiseOn2011-11-01T11:34:08Z</wfdata:raiseOn>\n") .append(" </wfdata:Workflow>\n") .append("</core:Container>\n"); session.execute(qs.toString()); }
/** * Replaces a node and declares the 'wfdata' prefix on the 'wfdata:Workflow' node. * * @param uri Document uri. * @throws java.io.IOException IO exception */ private void replaceNode2(String uri) throws java.io.IOException { java.lang.StringBuilder qs = new java.lang.StringBuilder("xquery\n"); qs.append("declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C%22;%5Cn"); qs.append("declare namespace core = "http://rdfs.cyim.com/CoreContent#%5C%22;%5Cn"); qs.append("declare namespace wfdata = "http://rdfs.cyim.com/WorkflowData#%5C%22;%5Cn"); qs.append("replace node /rdf:RDF/*[@rdf:about="" + uri + ""] with <core:Container rdf:about="" + uri + "" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C" xmlns:core="http://rdfs.cyim.com/CoreContent#%5C%22%3E%5Cn") .append(" <wfdata:Workflow xmlns:wfdata="http://rdfs.cyim.com/WorkflowData#%5C%22%3E%5Cn") .append(" wfdata:raiseOn2011-11-01T11:34:08Z</wfdata:raiseOn>\n") .append(" </wfdata:Workflow>\n") .append("</core:Container>\n"); session.execute(qs.toString()); }
/** * Query. Select depending on added node. * * @param expected Number of expected results. * @throws java.io.IOException IO exception */ private void query(int expected) throws java.io.IOException { // Query using wildcards. java.lang.StringBuilder qs = new java.lang.StringBuilder("xquery\n"); qs.append("declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C%22;%5Cn"); qs.append("for $c in /rdf:RDF/*[//*:raiseOn<"2011-11-02T14:19:07Z"]\n"); qs.append("return <item about="{data($c/@rdf:about)}" raiseOn="{data($c//*:raiseOn)}"/>\n"); String results = session.execute(qs.toString()); System.out.println("\n" + qs.toString() + "\n" + results); Assert.assertEquals("Missing results!", expected, results.isEmpty()?0:results.split("\r\n|\r|\n").length);
// Query using namespace. qs = new java.lang.StringBuilder("xquery\n"); qs.append("declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#%5C%22;%5Cn"); qs.append("declare namespace wfdata = "http://rdfs.cyim.com/WorkflowData#%5C%22;%5Cn"); qs.append("for $c in /rdf:RDF/*[//wfdata:raiseOn<"2011-11-02T14:19:07Z"]\n"); qs.append("return <item about="{data($c/@rdf:about)}" raiseOn="{data($c//wfdata:raiseOn)}"/>\n"); results = session.execute(qs.toString()); System.out.println("\n" + qs.toString() + "\n" + results); Assert.assertEquals("Missing results!", expected, results.isEmpty()?0:results.split("\r\n|\r|\n").length); }
/** * Test entry point. * @throws java.io.IOException IO exception */ @Test public void run() throws java.io.IOException { System.out.println("Query using unchanged documents."); query(0);
System.out.println("\nInserts a node to doc/1."); insertNode("doc/1");
System.out.println("\nQuery. Should get 1 document."); query(1);
System.out.println("\nReplaces a node in doc/2 and declares the 'wfdata' prefix on the 'core:Container' node.\n."); replaceNode("doc/2");
System.out.println("\nQuery. Should get 2 documents."); query(2);
System.out.println("\nReplaces a node in doc/3 and declares the 'wfdata' prefix on the 'wfdata:Workflow' node.\n."); replaceNode2("doc/3");
System.out.println("\nDatabase content:"); System.out.println(session.execute("xquery /"));
System.out.println("\nQuery. Should get 3 documents."); System.out.println("This test is going to fail without wildcards as if the new node linked to 'wfdata' prefix was not seen."); query(3); } }