changeset 18:78e783c39ef6

~ enhance the xpath wrapper
author Alexandre Bertails <bertails@w3.org>
date Wed, 03 Mar 2010 18:58:57 -0500
parents ba437c299c6a
children ce91c945e3d0
files src/main/scala/Main.scala src/main/scala/XML.scala
diffstat 2 files changed, 40 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/scala/Main.scala	Wed Mar 03 18:14:28 2010 -0500
+++ b/src/main/scala/Main.scala	Wed Mar 03 18:58:57 2010 -0500
@@ -1,6 +1,8 @@
 package org.w3.prc
 
 import org.w3.util._
+import org.w3.util.xml._
+import org.w3.util.xml.XPathQuery._
 import scala.xml.Elem
 
 /**
@@ -11,7 +13,7 @@
   /**
    * the inner parsed XML document from the url
    */
-  val doc:xml.Node = xml.Node.htmlNode(url)
+  val doc:Node = Node.htmlNode(url)
 
   final val divHead = "//html:div[@class='head']"
 
@@ -38,7 +40,7 @@
     val sect = doc.evaluateSingle(sectXPath).get
     // the rights dds are right under the previous section
     val ddsXPath = "$sect/following-sibling::html:dd[preceding-sibling::html:dt[1] is $sect]"
-    val dds = sect.evaluate(ddsXPath, "sect" -> sect)
+    val dds = sect.evaluate(ddsXPath % "sect" -> sect)
     // parse and inject the found editors into Editor
     dds map (dd => Editor.parse(dd.text)) toSeq
   }
@@ -48,10 +50,10 @@
     val dtXPath = versionblock + "/html:dt[matches(normalize-space(.),'version','i') and matches(normalize-space(.),'" + m + "','i')][1]"
     val dt = doc.evaluateSingle(dtXPath).get
     val ddXPath = "$dt/following-sibling::html:dd[preceding-sibling::html:dt[1] is $dt]"
-    val dd = dt.evaluateSingle(ddXPath, "dt" -> dt).get
+    val dd = dt.evaluateSingle(ddXPath % "dt" -> dt).get
     val vurisXPath = "$dd//html:a/@href"
     // val htmls = dd flatMap (dd => dd.evaluateAsString(vurisXPath, "dd" -> dd))
-    val htmls = dd.evaluate(vurisXPath, "dd" -> dd) map (_.normalizeSpace)
+    val htmls = dd.evaluate(vurisXPath % "dd" -> dd) map (_.normalizeSpace)
     htmls toSeq
   }
 
--- a/src/main/scala/XML.scala	Wed Mar 03 18:14:28 2010 -0500
+++ b/src/main/scala/XML.scala	Wed Mar 03 18:58:57 2010 -0500
@@ -106,25 +106,39 @@
 
 }
 
+case class XPathQuery(query:String, svars:Map[String, String], nvars:Map[String, Node]) {
+  def %(boundvar:String):BoundXPathQuery = BoundXPathQuery(boundvar, query, svars, nvars)
+}
+
+case class BoundXPathQuery(boundvar:String, query:String, svars:Map[String, String], nvars:Map[String, Node]) {
+  def ->(value:String):XPathQuery = XPathQuery(query, svars+(boundvar -> value), nvars)
+  def ->(value:Int):XPathQuery = XPathQuery(query, svars+(boundvar -> value.toString), nvars)
+  def ->(value:Node):XPathQuery = XPathQuery(query, svars, nvars+(boundvar -> value))
+}
+
+object XPathQuery {
+  implicit def apply(query:String):XPathQuery = XPathQuery(query, Map[String, String](), Map[String, Node]())
+}
+
 case class Node(node:XdmNode, namespaces:Map[String, String]) {
 
   /**
    * prepare an XPath selector ready to be used against this node
    * xhtml namespace is assumed
    */
-  def getXPathSelector(xpath:String, variables:List[(String, Node)]):XPathSelector = {
+  def getXPathSelector(xpath:XPathQuery):XPathSelector = {
     val proc:Processor = node.getProcessor
     val xpathCompiler:XPathCompiler = proc.newXPathCompiler();
     for((prefix, uri) <- namespaces)
       xpathCompiler.declareNamespace(prefix, uri)
-    for((v, _) <- variables)
-      xpathCompiler.declareVariable(new QName(v),
-				    ItemType.ANY_NODE,
-				    OccurrenceIndicator.ONE_OR_MORE)
-    val selector:XPathSelector = xpathCompiler.compile(xpath).load()
+    def declare(v:String) = xpathCompiler.declareVariable(new QName(v),
+							  ItemType.ANY_NODE,
+							  OccurrenceIndicator.ONE_OR_MORE)
+    for((v, _) <- xpath.svars) declare(v)
+    for((v, _) <- xpath.nvars) declare(v)
+    val selector:XPathSelector = xpathCompiler.compile(xpath.query).load()
     selector.setContextItem(node)
-    for((v, n) <- variables)
-      selector.setVariable(new QName(v), n.node)
+    for((v, n) <- xpath.nvars) selector.setVariable(new QName(v), n.node)
     selector
   }
 
@@ -137,8 +151,8 @@
    * evaluates an xpath expression against a document
    * TODO
    */
-  def evaluateSingle(xpath:String, variables:(String, Node)*):Option[Node] = {
-    val selector = getXPathSelector(xpath, variables.toList)
+  def evaluateSingle(xpath:XPathQuery):Option[Node] = {
+    val selector = getXPathSelector(xpath)
     Option(selector.evaluateSingle()) flatMap ((item:XdmItem) => Some(Node(item.asInstanceOf[XdmNode], namespaces)))
   }
 
@@ -146,26 +160,26 @@
    * evaluates an xpath expression against a document
    * TODO
    */
-  def evaluate(xpath:String, variables:(String, Node)*):Iterator[Node] = {
-    val selector = getXPathSelector(xpath, variables.toList)
+  def evaluate(xpath:XPathQuery):Iterator[Node] = {
+    val selector = getXPathSelector(xpath)
     JIteratorWrapper(selector.iterator()) map ((item:XdmItem) => Node(item.asInstanceOf[XdmNode], namespaces))
   }
 
-  private def evaluateAsXdmAtomicValues(xpath:String, variables:List[(String, Node)]):Iterator[XdmAtomicValue] = {
-    val selector = getXPathSelector(xpath, variables)
+  private def evaluateAsXdmAtomicValues(xpath:XPathQuery):Iterator[XdmAtomicValue] = {
+    val selector = getXPathSelector(xpath)
     JIteratorWrapper(selector.iterator()) map (_.asInstanceOf[XdmAtomicValue])
   }
 
-  private def evaluateSingleAsXdmAtomicValues(xpath:String, variables:List[(String, Node)]):Option[XdmAtomicValue] = {
-    val selector = getXPathSelector(xpath, variables)
+  private def evaluateSingleAsXdmAtomicValues(xpath:XPathQuery):Option[XdmAtomicValue] = {
+    val selector = getXPathSelector(xpath)
     Option(selector.evaluateSingle()) flatMap ((item:XdmItem) => Some(item.asInstanceOf[XdmAtomicValue]))
   }
 
-  def evaluateAsString(xpath:String, variables:(String, Node)*):Iterator[String] =
-    evaluateAsXdmAtomicValues(xpath, variables.toList) map (_.toString)
+  def evaluateAsString(xpath:XPathQuery):Iterator[String] =
+    evaluateAsXdmAtomicValues(xpath) map (_.toString)
 
-  def evaluateSingleAsString(xpath:String, variables:(String, Node)*):Option[String] =
-    evaluateSingleAsXdmAtomicValues(xpath, variables.toList) map (_.toString)
+  def evaluateSingleAsString(xpath:XPathQuery):Option[String] =
+    evaluateSingleAsXdmAtomicValues(xpath) map (_.toString)
 
   override def toString = node.toString
 
Set up and maintained by W3C Systems Team, please report bugs to sysreq@w3.org.

W3C would like to thank Microsoft who donated the server that allows us to run this service.