[gxml/xpath: 3/8] gxml/: add initial XPath files, Error, Expression, NSResolver, and Result



commit 90bc0b1319693798f6a0ede8a7d1ba3b6a304494
Author: Adam Ples <ples adam gmail com>
Date:   Mon Oct 14 05:29:09 2013 -0400

    gxml/: add initial XPath files, Error, Expression, NSResolver, and Result

 gxml/XPathError.vala      |   43 +++++++++
 gxml/XPathExpression.vala |  118 +++++++++++++++++++++++++
 gxml/XPathNSResolver.vala |   64 ++++++++++++++
 gxml/XPathResult.vala     |  208 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 433 insertions(+), 0 deletions(-)
---
diff --git a/gxml/XPathError.vala b/gxml/XPathError.vala
new file mode 100644
index 0000000..743f3db
--- /dev/null
+++ b/gxml/XPathError.vala
@@ -0,0 +1,43 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* XPathError.vala
+ *
+ * Copyright (C) 2011-2013  Richard Schwarting <aquarichy gmail com>
+ * Copyright (C) 2011  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Richard Schwarting <aquarichy gmail com>
+ *      Daniel Espinosa <esodan gmail com>
+ */
+namespace GXml.XPath {
+       /* XPATH:TODO: can we do subnamespaces and have it work in C well?  I was told no when I started GXml 
*/
+
+       /**
+        * Describes various error states. For more, see
+        * [[http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226/xpath.html#XPathException]]
+        */
+       public errordomain Error {
+               /**
+                * If the expression has a syntax error or otherwise is not a legal expression
+                * according to the rules of the specific XPathEvaluator or contains specialized
+                * extension functions or variables not supported by this implementation.
+                */
+               INVALID_EXPRESSION,
+               /**
+                * If the expression cannot be converted to return the specified type.
+                */
+               TYPE
+       }
+}
diff --git a/gxml/XPathExpression.vala b/gxml/XPathExpression.vala
new file mode 100644
index 0000000..a5d9529
--- /dev/null
+++ b/gxml/XPathExpression.vala
@@ -0,0 +1,118 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* XPathExpression.vala
+ *
+ * Copyright (C) 2011-2013  Richard Schwarting <aquarichy gmail com>
+ * Copyright (C) 2011  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Richard Schwarting <aquarichy gmail com>
+ *      Daniel Espinosa <esodan gmail com>
+ */
+namespace GXml.XPath {
+
+       /**
+        * Represents compiled XPath expression. Such expression can be then evaluated
+        * multiple times over one or multiple documents.
+        */
+       public class Expression : Object {
+
+               internal Xml.XPath.CompExpr* expression;
+
+               /**
+                * Object used to resolve namespace prefixes in XPath expressions.
+                */
+               public NSResolver ns_resolver;
+
+               /**
+                * Creates compiled XPath expression from string with specified namespace
+                * resolver.
+                * @throws XPath.Error when provided expression is invalid XPath
+                */
+               public Expression (string expr, NSResolver? ns_resolver = null) throws XPath.Error {
+                       expression = Xml.XPath.compile(expr);
+                       if (expression == null)
+                               throw new XPath.Error.INVALID_EXPRESSION (xml_error_msg ());
+                       this.ns_resolver = ns_resolver;
+               }
+
+               /* Destructor */
+               ~Expression () {
+                       delete expression;
+               }
+
+               /**
+                * Evaluates XPath expression over DOM node and returns XPath.Result object.
+                * @param context_node context node for the evaluation of this XPath expression
+                * @param res_type type to cast resulting value to
+                * @return XPath.Result object containing result type and value
+                * @throws DomError when node type is not supported as context of evaluation
+                * @throws XPath.Error when supplied with invalid XPath expression
+                */
+               public Result evaluate (Node context_node,
+                       ResultType res_type = ResultType.ANY) throws XPath.Error, DomError
+               {
+                       Document doc = (context_node is Document) ? (Document) context_node : 
context_node.owner_document;
+                       doc.sync_dirty_elements ();
+
+                       Xml.XPath.Context context = new Xml.XPath.Context (doc.xmldoc);
+
+                       /* Node types supported by XPath are: Document, Element, Attribute, Text,
+                        * CDATASection, Comment, ProcessingInstruction and XPathNamespace.
+                        * BackedNode covers Document, Element, Comment, Text and CDATASection.
+                        */
+                       if (context_node is BackedNode) {
+                               context.node = ((BackedNode) context_node).node;
+                       }
+                       else if (context_node is Attr) {
+                               context.node = (Xml.Node *) ((Attr) context_node).node;
+                       }
+                       /* Not implemented */
+                       // else if (context_node is XPath.Namespace) {
+                       //  dunno
+                       //      context.node = (Xml.Node *) ((Namespace) context_node).node;
+                       // }
+                       else if (context_node is ProcessingInstruction) {
+                               /* There is no Xml.Node* field in ProcessingInstruction implementation */
+                               throw new DomError.NOT_SUPPORTED("Not implemented");
+                       }
+
+                       if (ns_resolver != null)
+                               foreach (var entry in ns_resolver.entries) {
+                                       if (entry.key == null || entry.value == null)
+                                               throw new XPath.Error.INVALID_EXPRESSION ("Namespace prefix " 
+
+                                                       "and/or URI cannot be null");
+                                       if (entry.key == "" || entry.value == "")
+                                               throw new XPath.Error.INVALID_EXPRESSION ("Namespace prefix " 
+
+                                                       "and/or URI cannot be empty strings");
+                                       if (context.register_ns (entry.key, entry.value) == -1)
+                                               throw new XPath.Error.INVALID_EXPRESSION (xml_error_msg ());
+                               }
+
+                       Xml.XPath.Object* xml_result = context.compiled_eval (expression);
+                       if (xml_result == null)
+                               throw new XPath.Error.INVALID_EXPRESSION (xml_error_msg ());
+                       Result result = new Result (doc, xml_result);
+
+                       if (res_type != ResultType.ANY) {
+                               /* *** Not implemented *** */
+                               // result.cast(res_type)
+                       }
+
+                       return result;
+               }
+
+       }
+}
diff --git a/gxml/XPathNSResolver.vala b/gxml/XPathNSResolver.vala
new file mode 100644
index 0000000..cbd80f1
--- /dev/null
+++ b/gxml/XPathNSResolver.vala
@@ -0,0 +1,64 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* XPathNSResolver.vala
+ *
+ * Copyright (C) 2011-2013  Richard Schwarting <aquarichy gmail com>
+ * Copyright (C) 2011  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Richard Schwarting <aquarichy gmail com>
+ *      Daniel Espinosa <esodan gmail com>
+ */
+namespace GXml.XPath {
+
+       /**
+        * Structure used for bounding prefixes with namespace URIs.
+        *
+        * [[http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226/xpath.html#XPathNSResolver]]
+        */
+       public class NSResolver : Gee.TreeMap<string, string> {
+
+               /**
+                * Creates namespace resolver with prefix to URI mapping provided as flat
+                * array of strings (first element is prefix, second is namespace URI for
+                * that prefix, then another prefix and so on).
+                */
+               public NSResolver (string? prefix1 = null, ...) {
+                       var l = va_list ();
+                       string? prefix = prefix1; /* One implicit argument is required */
+                       string? uri = l.arg ();
+
+                       base ();
+
+                       while (true) {
+                               if (prefix == null || uri == null)
+                                       break;
+                               this[prefix] = uri;
+                               prefix = l.arg ();
+                               if (prefix == null)
+                                       break;
+                               uri = l.arg ();
+                       }
+               }
+
+               /**
+                * Returns the associated namespace URI or null if none is found.
+                */
+               public string? lookup_namespace_uri (string prefix) {
+                       return this[prefix];
+               }
+
+       }
+}
diff --git a/gxml/XPathResult.vala b/gxml/XPathResult.vala
new file mode 100644
index 0000000..1ee2477
--- /dev/null
+++ b/gxml/XPathResult.vala
@@ -0,0 +1,208 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* XPathResult.vala
+ *
+ * Copyright (C) 2011-2013  Richard Schwarting <aquarichy gmail com>
+ * Copyright (C) 2011  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Richard Schwarting <aquarichy gmail com>
+ *      Daniel Espinosa <esodan gmail com>
+ */
+namespace GXml.XPath {
+
+       /**
+        * Data type of XPathResult (see 
[[http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226/xpath.html#XPathResult]]).
+        */
+       public enum ResultType {
+               /**
+                * This code does not represent a specific type. An evaluation of an XPath
+                * expression will never produce this type. If this type is requested, then
+                * the evaluation returns whatever type naturally results from evaluation
+                * of the expression.
+                */
+               ANY,
+               NUMBER,
+               STRING,
+               BOOLEAN,
+               UNORDERED_NODE_ITERATOR,
+               ORDERED_NODE_ITERATOR,
+               UNORDERED_NODE_SNAPSHOT,
+               ORDERED_NODE_SNAPSHOT,
+               ANY_UNORDERED_NODE,
+               FIRST_ORDERED_NODE
+       }
+
+       /**
+        * Represents result of XPath expression evaluation.
+        */
+       public class Result : GLib.Object {
+
+               internal Gee.List<Node> nodeset;
+               internal Xml.XPath.Object* object;
+               /**
+                * Type of result value
+                */
+               public ResultType  result_type { get; private set; }
+
+               /**
+                * Returns value for number result
+                */
+               public double number_value {
+                       get {
+                               // "properties throwing errors are not supported yet"
+                               // if (result_type != ResultType.NUMBER)
+                               //      throw new XPath.Error.TYPE ("Result type is not number");
+                               return object->floatval;
+                       }
+               }
+
+               /**
+                * Returns value for string result
+                */
+               public string string_value {
+                       get {
+                               // if (result_type != ResultType.STRING)
+                               //      throw new XPath.Error.TYPE ("Result type is not string");
+                               return object->stringval;
+                       }
+               }
+
+               /**
+                * Returns value for boolean result
+                */
+               public bool boolean_value {
+                       get {
+                               // if (result_type != ResultType.BOOLEAN)
+                               //      throw new XPath.Error.TYPE ("Result type is not boolean");
+                               return object->boolval != 0;
+                       }
+               }
+
+               /**
+                * Returns value for node snapshot result
+                */
+               public Gee.List<Node> nodeset_value {
+                       get {
+                               // if (result_type != ResultType.ORDERED_NODE_SNAPSHOT)
+                               //      throw new XPath.Error.TYPE ("Result type is not node snapshot");
+                               return this.nodeset;
+                       }
+               }
+
+               /**
+                * Returns length of node snapshot
+                */
+               public int snapshot_length {
+                       get {
+                               // if (result_type != ResultType.ORDERED_NODE_SNAPSHOT)
+                               //      throw new XPath.Error.TYPE ("Result type is not node snapshot");
+                               return this.nodeset.size;
+                       }
+               }
+
+               /* protected for tests */
+               /**
+                * Creates XPath result from libxml2 xmlXPathObject.
+                * @param doc owner document of context node
+                * @param object XPath result object from libxml2; created object takes
+                *   responsibility of deleting it
+                * @throws XPath.Error.TYPE when result type of object is invalid
+                */
+               protected Result(Document doc, Xml.XPath.Object* object)
+                       throws XPath.Error
+                       requires (object != null)
+               {
+                       this.object = object;
+
+                       switch (object->type) {
+                               case Xml.XPath.ObjectType.UNDEFINED:
+                                       throw new XPath.Error.TYPE ("Result type cannot be undefined");
+
+                               case Xml.XPath.ObjectType.NODESET:
+                                       result_type = ResultType.ORDERED_NODE_SNAPSHOT;
+                                       nodeset = new Gee.ArrayList<Node> ();
+                                       for (var i = 0, l = object->nodesetval->length (); i < l; ++i)
+                                               nodeset.add (doc.lookup_node (object->nodesetval->item (i)));
+                                       break;
+
+                               case Xml.XPath.ObjectType.BOOLEAN:
+                                       result_type = ResultType.BOOLEAN;
+                                       break;
+                               case Xml.XPath.ObjectType.NUMBER:
+                                       result_type = ResultType.NUMBER;
+                                       break;
+                               case Xml.XPath.ObjectType.STRING:
+                                       result_type = ResultType.STRING;
+                                       break;
+
+                               case Xml.XPath.ObjectType.POINT:
+                                       /* *** Not implemented *** */
+                                       break;
+                               case Xml.XPath.ObjectType.RANGE:
+                                       /* *** Not implemented *** */
+                                       break;
+                               case Xml.XPath.ObjectType.LOCATIONSET:
+                                       /* *** Not implemented *** */
+                                       break;
+                               case Xml.XPath.ObjectType.USERS:
+                                       /* *** Not implemented *** */
+                                       break;
+                               case Xml.XPath.ObjectType.XSLT_TREE:
+                                       /* *** Not implemented *** */
+                                       break;
+
+                               default:
+                                       throw new XPath.Error.TYPE ("Unsupported result type");
+                       }
+               }
+
+               /* Destructor */
+               ~XPathResult () {
+                       delete object;
+               }
+
+               /**
+                * Returns n-th node from snapshot
+                */
+               public Node snapshot_item(int n) throws XPath.Error {
+                       if (result_type != ResultType.ORDERED_NODE_SNAPSHOT)
+                               throw new XPath.Error.TYPE ("Result type is not node snapshot");
+                       return this.nodeset[n];
+               }
+
+               /**
+                * Converts XPath result value to bool.
+                */
+               public bool to_bool() {
+                        return Xml.XPath.cast_to_boolean (object);
+               }
+
+               /**
+                * Converts XPath result value to number.
+                */
+               public double to_number () {
+                        return Xml.XPath.cast_to_number (object);
+               }
+
+               /**
+                * Converts XPath result value to string.
+                */
+               public string to_string () {
+                        return Xml.XPath.cast_to_string (object);
+               }
+
+       }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]