XML: it is now possible to make a XPath query in starting on a given element 05/5505/4
Calixte DENIZET [Wed, 23 Nov 2011 16:24:27 +0000 (17:24 +0100)]
Change-Id: Ib3af7d85fc2620f08b4c4dec62484772c4396915

scilab/modules/xml/help/en_US/xmlXPath.xml
scilab/modules/xml/sci_gateway/cpp/sci_xmlXPath.cpp
scilab/modules/xml/src/cpp/XMLDocument.cpp
scilab/modules/xml/src/cpp/XMLDocument.hxx
scilab/modules/xml/tests/unit_tests/xmlXPath.dia.ref [moved from scilab/modules/xml/tests/unit_tests/xmlXpath.tst with 81% similarity]
scilab/modules/xml/tests/unit_tests/xmlXPath.tst [moved from scilab/modules/xml/tests/unit_tests/xmlXpath.dia.ref with 79% similarity]

index c695250..b48281f 100644 (file)
   <refsynopsisdiv>
     <title>Calling Sequence</title>
     <synopsis>
-      result = xmlXPath(xmlDoc, queryStr [, namespaces])
+      result = xmlXPath(xmlObj, queryStr [, namespaces])
     </synopsis>
   </refsynopsisdiv>
   <refsection>
     <title>Arguments</title>
     <variablelist>
       <varlistentry>
-        <term>xmlDoc</term>
+        <term>xmlObj</term>
         <listitem>
-          <para>xmlDoc, a XML mlist typed XMLDoc</para>
+          <para>xmlObj, a XML mlist typed XMLDoc or XMLElem</para>
         </listitem>
       </varlistentry>
       <varlistentry>
@@ -55,7 +55,7 @@
   </refsection>
   <refsection>
     <title>Description</title>
-    <para>Make an XPath query on a document. If you need to use namespaces, then you must define them in using the optional argument.</para>
+    <para>Make an XPath query on a document or in starting on an element. If you need to use namespaces, then you must define them in using the optional argument.</para>
     <para>For more informations about XPath, you can read the <ulink url="http://www.w3.org/TR/1999/REC-xpath-19991116/">W3C recommandation</ulink>.</para>
   </refsection>
   <refsection>
     xmlXPath(doc, "//scilab:a", ["scilab" "http://www.scilab.org"]) // => OK
 
     xmlClose(doc);
+
+    // Query starting on an element
+    doc = xmlReadStr("<root att=""attribute""><a a1=""A1"" a2=""A2"" a3=""A3""><b>Hello</b><c>Scilab</c><b>World</b></a><b>Nothing</b></root>");
+    e = doc.root.children(1);
+
+    // Get the attributes of e
+    xp = xmlXPath(e, "@*");
+    xmlAsText(xp)
+
+    // Get the 'b' from e
+    xp = xmlXPath(e, "b");
+    xmlAsText(xp)
+
+    xmlClose(doc);
     ]]></programlisting>
   </refsection>
   <refsection role="see also">
index 07af05f..b03cc60 100644 (file)
@@ -24,6 +24,7 @@ extern "C"
 
 #include "XMLObject.hxx"
 #include "XMLDocument.hxx"
+#include "XMLElement.hxx"
 #include "XMLXPath.hxx"
 #include "XMLNodeSet.hxx"
 
@@ -35,6 +36,7 @@ int sci_xmlXPath(char * fname, unsigned long fname_len)
     int id;
     SciErr err;
     org_modules_xml::XMLDocument * doc;
+    XMLElement * where = 0;
     const XMLXPath * xpath;
     int * addr = 0;
     char * query = 0;
@@ -42,6 +44,7 @@ int sci_xmlXPath(char * fname, unsigned long fname_len)
     int row = 0;
     int col = 0;
     char ** namespaces = 0;
+    int isElem = 0;
 
     CheckLhs(1, 1);
     CheckRhs(2, 3);
@@ -53,18 +56,33 @@ int sci_xmlXPath(char * fname, unsigned long fname_len)
         return 0;
     }
 
-    if (!isXMLDoc(addr, pvApiCtx))
+    isElem = isXMLElem(addr, pvApiCtx);
+
+    if (!isElem && !isXMLDoc(addr, pvApiCtx))
     {
-        Scierror(999, gettext("%s: Wrong type for input argument #%d: A %s expected.\n"), fname, 1, "XMLDoc");
+        Scierror(999, gettext("%s: Wrong type for input argument #%d: A XMLDoc or a XMLElem expected.\n"), fname, 1);
         return 0;
     }
 
     id = getXMLObjectId(addr, pvApiCtx);
-    doc = XMLObject::getFromId<org_modules_xml::XMLDocument>(id);
-    if (!doc)
+    if (isElem)
     {
-        Scierror(999, gettext("%s: XML document does not exist.\n"), fname);
-        return 0;
+        where = XMLObject::getFromId<XMLElement>(id);
+        if (!where)
+        {
+            Scierror(999, gettext("%s: XML element does not exist.\n"), fname);
+            return 0;
+        }
+        doc = const_cast<org_modules_xml::XMLDocument *>(&(where->getXMLDocument()));
+    }
+    else
+    {
+        doc = XMLObject::getFromId<org_modules_xml::XMLDocument>(id);
+        if (!doc)
+        {
+            Scierror(999, gettext("%s: XML document does not exist.\n"), fname);
+            return 0;
+        }
     }
 
     err = getVarAddressFromPosition(pvApiCtx, 2, &addr);
@@ -116,7 +134,7 @@ int sci_xmlXPath(char * fname, unsigned long fname_len)
         getAllocatedMatrixOfString(pvApiCtx, addr, &row, &col, &namespaces);
     }
 
-    xpath = doc->makeXPathQuery(const_cast<const char *>(query), namespaces, row, &error);
+    xpath = doc->makeXPathQuery(const_cast<const char *>(query), namespaces, row, where, &error);
     freeAllocatedSingleString(query);
     if (namespaces)
     {
index 30557a5..c572164 100644 (file)
@@ -115,7 +115,7 @@ namespace org_modules_xml
         return static_cast<void *>(document);
     }
 
-    const XMLXPath * XMLDocument::makeXPathQuery(const char * query, char ** namespaces, int length, std::string * error)
+    const XMLXPath * XMLDocument::makeXPathQuery(const char * query, char ** namespaces, int length, const XMLElement * e, std::string * error)
     {
         if (errorXPathBuffer)
         {
@@ -131,6 +131,11 @@ namespace org_modules_xml
             return 0;
         }
 
+        if (e)
+        {
+            ctxt->node = (xmlNode *)e->getRealXMLPointer();
+        }
+
         if (namespaces)
         {
             for (int i = 0; i < length; i++)
index b1b7ab2..928c1cb 100644 (file)
@@ -123,10 +123,11 @@ namespace org_modules_xml
          * @param query the XPath query
          * @param namespaces an a matrix nx2 containing mapping between prefix and href
          * @param length the number of namespaces
+         * @param the node from where start the query
          * @param error a pointer to a string which will receive the error message
          * @return a pointer on a XPath object
          */
-        const XMLXPath * makeXPathQuery(const char * query, char ** namespaces, int length, std::string * error);
+        const XMLXPath * makeXPathQuery(const char * query, char ** namespaces, int length, const XMLElement * e, std::string * error);
 
         const XMLObject * getXMLObjectParent() const;
         const std::string dump(bool indent) const;
@@ -4,8 +4,6 @@
 //
 //  This file is distributed under the same license as the Scilab package.
 // ===========================================================================
-
-
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
 titles=xmlXPath(xmlFile, "/bookstore/book/title");
 assert_checkequal(titles.size,5);
@@ -18,27 +16,22 @@ assert_checkequal(titles(5).type,"XML_ELEMENT_NODE");
 attribs=titles(4).attributes;
 assert_checkequal(titles(4).attributes.size,[]);
 assert_checkequal(attribs.lang,"en");
-
 // Get all the books where the price is more than 35 euros
 moreThan35eList=xmlXPath(xmlFile,"/bookstore/book[price>35]/title");
 assert_checkequal(moreThan35eList.size,2);
 assert_checkequal(size(moreThan35eList),[1,2]); 
 assert_checkequal(moreThan35eList(1).content,"XQuery Kick Start");
 assert_checkequal(moreThan35eList(2).content,"Learning XML");
-
 // Get all the free books 
 freeBooks=xmlXPath(xmlFile,"/bookstore/book[price=0]/title");
 assert_checkequal(freeBooks.size,1);
 assert_checkequal(size(freeBooks),[1,1]); 
 assert_checkequal(freeBooks(1).content,"Scilab rox");
-
 xmlClose(xmlFile);
-
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/sep_69_example.xml");
 titles=xmlXPath(xmlFile, "/root/hello");
 assert_checkequal(titles.size,2);
 xmlClose(xmlFile);
-
 xmlFile=xmlRead(SCI+"/etc/modules.xml");
 content=xmlDump(xmlFile);
 assert_checktrue(length(content)>0);
@@ -46,23 +39,17 @@ assert_checktrue(size(content)>=[1,1]);
 xmlClose(xmlFile);
 // Close the file a second time
 assert_checkerror("xmlClose(xmlFile)",gettext("xmlClose: XML document does not exist."));
-
-
 xmlClasspath=xmlRead(SCI+"/etc/classpath.xml");
 jarPath=xmlXPath(xmlClasspath, "//classpaths/path[@load=''onUse'']/load");
 assert_checktrue(length(jarPath(1).attributes.on)>0); // Should be Console
 // if the order of classpath.xml does not change
 assert_checkequal(grep(jarPath(1).parent.attributes.value,".jar"),1);
 assert_checkequal(jarPath(1).parent.attributes.load,"onUse");
-
 jarPath=xmlXPath(xmlClasspath, "//classpaths/path[@load!=''onUse'']");
 assert_checktrue(length(jarPath(1).attributes.value)>0);
 assert_checkequal(jarPath(1).attributes.load,"startup");
 assert_checkequal(jarPath(1).parent.name,"classpaths"); // it is the root dir
-
-
 xmlClose(xmlClasspath);
-
 xmlFile=xmlRead(SCI+"/etc/modules.xml");
 xmlFile2=xmlRead(SCI+"/etc/classpath.xml");
 content=xmlDump(xmlFile);
@@ -76,18 +63,30 @@ xmlClose(xmlFile);
 xmlClose(xmlFile2);
 // Close the file a second time
 assert_checkerror("xmlClose(xmlFile)","xmlClose: XML document does not exist.");
-
-
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
 titles=xmlXPath(xmlFile, "/bookstore/book/title");
 assert_checkequal(titles.name,["title","title","title","title","title"]);
 assert_checkequal(titles.content,["Everyday Italian","Harry Potter","XQuery Kick Start","Learning XML","Scilab rox"]);
-
 prices=xmlXPath(xmlFile, "/bookstore/book/price");
 assert_checkequal(prices.name,["price","price","price","price","price"]);
 assert_checkequal(prices.content,["30.00","29.99","49.99","39.95","0.0"]);
-
 titlesEmpty=xmlXPath(xmlFile, "/bookstore/book/prices");
 assert_checkequal(length(titlesEmpty),0);
-
 xmlClose(xmlFile);
+xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
+titles=xmlXPath(xmlFile, "/bookstore");
+results=xmlXPath(titles(1), "book[title=''Everyday Italian'']");
+assert_checkequal(length(results),1);
+assert_checkequal(results.name,"book");
+assert_checkequal(results.content,"Everyday ItalianGiada De Laurentiis200530.00");
+assert_checkequal(results(1).children(1).content,"Everyday Italian");
+xmlClose(xmlFile);
+doc = xmlReadStr("<root att=""attribute""><a a1=""A1"" a2=""A2"" a3=""A3""><b>Hello</b><c>Scilab</c><b>World</b></a><b>Nothing</b></root>");
+e = doc.root.children(1);
+assert_checkequal(e.content,"HelloScilabWorld");
+assert_checkequal(e.name,"a");
+xp = xmlXPath(e, "@*");
+assert_checkequal(["A1","A2","A3"],xmlAsText(xp));
+xp = xmlXPath(e, "b");
+assert_checkequal(["Hello","World"],xmlAsText(xp));
+xmlClose(doc);
@@ -4,6 +4,8 @@
 //
 //  This file is distributed under the same license as the Scilab package.
 // ===========================================================================
+
+
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
 titles=xmlXPath(xmlFile, "/bookstore/book/title");
 assert_checkequal(titles.size,5);
@@ -16,22 +18,27 @@ assert_checkequal(titles(5).type,"XML_ELEMENT_NODE");
 attribs=titles(4).attributes;
 assert_checkequal(titles(4).attributes.size,[]);
 assert_checkequal(attribs.lang,"en");
+
 // Get all the books where the price is more than 35 euros
 moreThan35eList=xmlXPath(xmlFile,"/bookstore/book[price>35]/title");
 assert_checkequal(moreThan35eList.size,2);
 assert_checkequal(size(moreThan35eList),[1,2]); 
 assert_checkequal(moreThan35eList(1).content,"XQuery Kick Start");
 assert_checkequal(moreThan35eList(2).content,"Learning XML");
+
 // Get all the free books 
 freeBooks=xmlXPath(xmlFile,"/bookstore/book[price=0]/title");
 assert_checkequal(freeBooks.size,1);
 assert_checkequal(size(freeBooks),[1,1]); 
 assert_checkequal(freeBooks(1).content,"Scilab rox");
+
 xmlClose(xmlFile);
+
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/sep_69_example.xml");
 titles=xmlXPath(xmlFile, "/root/hello");
 assert_checkequal(titles.size,2);
 xmlClose(xmlFile);
+
 xmlFile=xmlRead(SCI+"/etc/modules.xml");
 content=xmlDump(xmlFile);
 assert_checktrue(length(content)>0);
@@ -39,17 +46,23 @@ assert_checktrue(size(content)>=[1,1]);
 xmlClose(xmlFile);
 // Close the file a second time
 assert_checkerror("xmlClose(xmlFile)",gettext("xmlClose: XML document does not exist."));
+
+
 xmlClasspath=xmlRead(SCI+"/etc/classpath.xml");
 jarPath=xmlXPath(xmlClasspath, "//classpaths/path[@load=''onUse'']/load");
 assert_checktrue(length(jarPath(1).attributes.on)>0); // Should be Console
 // if the order of classpath.xml does not change
 assert_checkequal(grep(jarPath(1).parent.attributes.value,".jar"),1);
 assert_checkequal(jarPath(1).parent.attributes.load,"onUse");
+
 jarPath=xmlXPath(xmlClasspath, "//classpaths/path[@load!=''onUse'']");
 assert_checktrue(length(jarPath(1).attributes.value)>0);
 assert_checkequal(jarPath(1).attributes.load,"startup");
 assert_checkequal(jarPath(1).parent.name,"classpaths"); // it is the root dir
+
+
 xmlClose(xmlClasspath);
+
 xmlFile=xmlRead(SCI+"/etc/modules.xml");
 xmlFile2=xmlRead(SCI+"/etc/classpath.xml");
 content=xmlDump(xmlFile);
@@ -63,11 +76,41 @@ xmlClose(xmlFile);
 xmlClose(xmlFile2);
 // Close the file a second time
 assert_checkerror("xmlClose(xmlFile)","xmlClose: XML document does not exist.");
+
+
 xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
 titles=xmlXPath(xmlFile, "/bookstore/book/title");
 assert_checkequal(titles.name,["title","title","title","title","title"]);
 assert_checkequal(titles.content,["Everyday Italian","Harry Potter","XQuery Kick Start","Learning XML","Scilab rox"]);
+
 prices=xmlXPath(xmlFile, "/bookstore/book/price");
 assert_checkequal(prices.name,["price","price","price","price","price"]);
 assert_checkequal(prices.content,["30.00","29.99","49.99","39.95","0.0"]);
+
+titlesEmpty=xmlXPath(xmlFile, "/bookstore/book/prices");
+assert_checkequal(length(titlesEmpty),0);
+
 xmlClose(xmlFile);
+
+xmlFile=xmlRead(SCI+"/modules/xml/tests/unit_tests/w3cExample.xml");
+titles=xmlXPath(xmlFile, "/bookstore");
+results=xmlXPath(titles(1), "book[title=''Everyday Italian'']");
+assert_checkequal(length(results),1);
+assert_checkequal(results.name,"book");
+assert_checkequal(results.content,"Everyday ItalianGiada De Laurentiis200530.00");
+assert_checkequal(results(1).children(1).content,"Everyday Italian");
+xmlClose(xmlFile);
+
+doc = xmlReadStr("<root att=""attribute""><a a1=""A1"" a2=""A2"" a3=""A3""><b>Hello</b><c>Scilab</c><b>World</b></a><b>Nothing</b></root>");
+
+e = doc.root.children(1);
+assert_checkequal(e.content,"HelloScilabWorld");
+assert_checkequal(e.name,"a");
+
+xp = xmlXPath(e, "@*");
+assert_checkequal(["A1","A2","A3"],xmlAsText(xp));
+
+xp = xmlXPath(e, "b");
+assert_checkequal(["Hello","World"],xmlAsText(xp));
+
+xmlClose(doc);