[augeas-devel] augeas: master - Add preceding-sibling and following-sibling axes to path expressions

David Lutterkort lutter at fedoraproject.org
Fri Sep 11 21:39:49 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=07568dfdf09817ca330716f3822d666433ab19bf
Commit:        07568dfdf09817ca330716f3822d666433ab19bf
Parent:        6adfee876dcbff4f043a9380a1ede09d889acb09
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Thu Sep 10 16:57:17 2009 -0700
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Fri Sep 11 14:29:05 2009 -0700

Add preceding-sibling and following-sibling axes to path expressions

---
 src/pathx.c       |   34 +++++++++++++++++++++++++++++++---
 tests/xpath.tests |   20 ++++++++++++++++++++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/src/pathx.c b/src/pathx.c
index 466951c..2df3f7d 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -92,7 +92,9 @@ enum axis {
     DESCENDANT_OR_SELF,
     PARENT,
     ANCESTOR,
-    ROOT
+    ROOT,
+    PRECEDING_SIBLING,
+    FOLLOWING_SIBLING
 };
 
 /* This array is indexed by enum axis */
@@ -103,7 +105,9 @@ static const char *const axis_names[] = {
     "descendant-or-self",
     "parent",
     "ancestor",
-    "root"
+    "root",
+    "preceding-sibling",
+    "following-sibling"
 };
 
 static const char *const axis_sep = "::";
@@ -427,7 +431,9 @@ static struct nodeset *make_nodeset(struct state *state) {
 
 static void ns_add(struct nodeset *ns, struct tree *node,
                    struct state *state) {
-    // FIXME: Need to uniquify NS
+    for (int i=0; i < ns->used; i++)
+        if (ns->nodes[i] == node)
+            return;
     if (ns->used >= ns->size) {
         size_t size = 2 * ns->size;
         if (size < 10) size = 10;
@@ -1938,6 +1944,16 @@ static bool step_matches(struct step *step, struct tree *tree) {
     return (step->name == NULL || streqx(step->name, tree->label));
 }
 
+static struct tree *tree_prev(struct tree *pos) {
+    struct tree *node = NULL;
+    if (pos != pos->parent->children) {
+        for (node = pos->parent->children;
+             node->next != pos;
+             node = node->next);
+    }
+    return node;
+}
+
 static struct tree *step_first(struct step *step, struct tree *ctx) {
     struct tree *node = NULL;
     switch (step->axis) {
@@ -1958,6 +1974,12 @@ static struct tree *step_first(struct step *step, struct tree *ctx) {
             ctx = ctx->parent;
         node = ctx;
         break;
+    case PRECEDING_SIBLING:
+        node = tree_prev(ctx);
+        break;
+    case FOLLOWING_SIBLING:
+        node = ctx->next;
+        break;
     default:
         assert(0);
     }
@@ -2001,6 +2023,12 @@ static struct tree *step_next(struct step *step, struct tree *ctx,
             else
                 node = node->parent;
             break;
+        case PRECEDING_SIBLING:
+            node = tree_prev(node);
+            break;
+        case FOLLOWING_SIBLING:
+            node = node->next;
+            break;
         default:
             assert(0);
         }
diff --git a/tests/xpath.tests b/tests/xpath.tests
index ac93b91..d03cf79 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -195,3 +195,23 @@ test coerce-and-true /files['foo' and count(/files/etc/hosts/*) ]
      /files
 
 test coerce-and-false /files['' and count(/none) and /none]
+
+test preceding-sibling /files/etc/hosts/*/preceding-sibling::*[alias = 'localhost']
+     /files/etc/hosts/1
+
+test preceding-sibling-pred /files/etc/grub.conf/*[preceding-sibling::*[1] = ../default]
+     /files/etc/grub.conf/timeout = 5
+
+test preceding-sibling-pred2 /files/etc/grub.conf/*[preceding-sibling::*[1][self::default]]
+     /files/etc/grub.conf/timeout = 5
+
+test following-sibling /files/etc/hosts/1/*/following-sibling::alias
+     /files/etc/hosts/1/alias[1] = localhost
+     /files/etc/hosts/1/alias[2] = galia.watzmann.net
+     /files/etc/hosts/1/alias[3] = galia
+
+test following-sibling-pred /files/etc/hosts/1/*[following-sibling::alias]
+     /files/etc/hosts/1/ipaddr = 127.0.0.1
+     /files/etc/hosts/1/canonical = localhost.localdomain
+     /files/etc/hosts/1/alias[1] = localhost
+     /files/etc/hosts/1/alias[2] = galia.watzmann.net




More information about the augeas-devel mailing list