[gxml/xpath: 3/8] gxml/: add initial XPath files, Error, Expression, NSResolver, and Result
- From: Richard Hans Schwarting <rschwart src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml/xpath: 3/8] gxml/: add initial XPath files, Error, Expression, NSResolver, and Result
- Date: Tue, 15 Oct 2013 15:52:54 +0000 (UTC)
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]