aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--result/XPath/xptr/chaptersrange16
-rw-r--r--result/XPath/xptr/strrange20
-rw-r--r--test/XPath/docs/str1
-rw-r--r--test/XPath/xptr/chaptersrange1
-rw-r--r--test/XPath/xptr/strrange1
-rw-r--r--xpath.c8
-rw-r--r--xpointer.c211
8 files changed, 202 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index d2d4bfed..ff457c99 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Oct 13 18:24:31 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * xpath.c xpointer.c: XPointer reorder of ranges start/end and
+ string-range for empty strings
+ * test/XPath/docs/str test/XPath/xptr/chaptersrange
+ test/XPath/xptr/strrange: augmented the XPointer testsuite
+
Fri Oct 13 12:21:48 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* doc/xml.html doc/xmlmem.html: added a module describing memory
diff --git a/result/XPath/xptr/chaptersrange b/result/XPath/xptr/chaptersrange
index 0b85ee78..c1b9cde0 100644
--- a/result/XPath/xptr/chaptersrange
+++ b/result/XPath/xptr/chaptersrange
@@ -46,3 +46,19 @@ Object is a Location Set:
========================
Expression: xpointer(//chapter[position() = last()]/range-to(following::chapter[1]))
Object is empty (NULL)
+
+========================
+Expression: xpointer(//chapter[position() = 3]/range-to(/.//chapter[position() = 1]))
+Object is a Location Set:
+1 : Object is a range :
+ From node
+ ELEMENT chapter
+ ATTRIBUTE id
+ TEXT
+ content=chapter1
+ To node
+ ELEMENT chapter
+ ATTRIBUTE id
+ TEXT
+ content=chapter3
+
diff --git a/result/XPath/xptr/strrange b/result/XPath/xptr/strrange
index c48ba43b..c14ed917 100644
--- a/result/XPath/xptr/strrange
+++ b/result/XPath/xptr/strrange
@@ -74,3 +74,23 @@ Object is a Location Set:
TEXT
content=anced test
+
+========================
+Expression: xpointer(string-range(//seq, ''))
+Object is a Location Set:
+1 : Object is a collapsed range :
+ index 1 in node
+ TEXT
+ content=123
+2 : Object is a collapsed range :
+ index 2 in node
+ TEXT
+ content=123
+3 : Object is a collapsed range :
+ index 3 in node
+ TEXT
+ content=123
+4 : Object is a collapsed range :
+ index 4 in node
+ TEXT
+ content=123
diff --git a/test/XPath/docs/str b/test/XPath/docs/str
index 7127ca2a..547e54de 100644
--- a/test/XPath/docs/str
+++ b/test/XPath/docs/str
@@ -5,4 +5,5 @@
<p>a diff<em>i</em>cult one</p>
<p><p>a span</p>n<p>ing one</p></p>
<p><p>and an unbal</p><empty/>anced test</p>
+ <p>for empty string <seq>123</seq></p>
</chapter>
diff --git a/test/XPath/xptr/chaptersrange b/test/XPath/xptr/chaptersrange
index 0743111e..4d7a55b4 100644
--- a/test/XPath/xptr/chaptersrange
+++ b/test/XPath/xptr/chaptersrange
@@ -1,3 +1,4 @@
xpointer(//chapter[position() = 2]/range-to(following::chapter[1]))
xpointer(//chapter[position() <= 2]/range-to(following::chapter[1]))
xpointer(//chapter[position() = last()]/range-to(following::chapter[1]))
+xpointer(//chapter[position() = 3]/range-to(/.//chapter[position() = 1]))
diff --git a/test/XPath/xptr/strrange b/test/XPath/xptr/strrange
index 3c2aafce..32319273 100644
--- a/test/XPath/xptr/strrange
+++ b/test/XPath/xptr/strrange
@@ -3,3 +3,4 @@ xpointer(string-range(//p, 'test'))
xpointer(string-range(//p, 'difficult'))
xpointer(string-range(//p, 'spanning'))
xpointer(string-range(//p, 'unbalanced'))
+xpointer(string-range(//seq, ''))
diff --git a/xpath.c b/xpath.c
index 371ecbbc..78152993 100644
--- a/xpath.c
+++ b/xpath.c
@@ -2692,9 +2692,9 @@ xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
void
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CHECK_ARITY(0);
- if (ctxt->context->proximityPosition > 0) {
+ if (ctxt->context->proximityPosition >= 0) {
valuePush(ctxt,
- xmlXPathNewFloat((double) ctxt->context->proximityPosition));
+ xmlXPathNewFloat((double) ctxt->context->proximityPosition));
#ifdef DEBUG_EXPR
fprintf(xmlXPathDebug, "position() : %d\n",
ctxt->context->proximityPosition);
@@ -4772,14 +4772,14 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
ctxt->context->node = NULL;
if ((oldset == NULL) || (oldset->nodeNr == 0)) {
- xmlXPathEvalExpr(ctxt);
- CHECK_ERROR;
ctxt->context->contextSize = 0;
ctxt->context->proximityPosition = 0;
+ xmlXPathEvalExpr(ctxt);
res = valuePop(ctxt);
if (res != NULL)
xmlXPathFreeObject(res);
valuePush(ctxt, obj);
+ CHECK_ERROR;
} else {
/*
* Save the expression pointer since we will have to evaluate
diff --git a/xpointer.c b/xpointer.c
index 3403bc3f..9e32688e 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -55,6 +55,89 @@ extern FILE *xmlXPathDebug;
************************************************************************/
/**
+ * xmlXPtrCmpPoints:
+ * @node1: the first node
+ * @index1: the first index
+ * @node2: the second node
+ * @index2: the second index
+ *
+ * Compare two points w.r.t document order
+ *
+ * Returns -2 in case of error 1 if first point < second point, 0 if
+ * that's the same point, -1 otherwise
+ */
+int
+xmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) {
+ int depth1, depth2;
+ xmlNodePtr cur, root;
+
+ if ((node1 == NULL) || (node2 == NULL))
+ return(-2);
+ /*
+ * a couple of optimizations which will avoid computations in most cases
+ */
+ if (node1 == node2) {
+ if (index1 < index2)
+ return(1);
+ if (index1 > index2)
+ return(-1);
+ return(0);
+ }
+ if (node1 == node2->prev)
+ return(1);
+ if (node1 == node2->next)
+ return(-1);
+
+ /*
+ * compute depth to root
+ */
+ for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
+ if (cur == node1)
+ return(1);
+ depth2++;
+ }
+ root = cur;
+ for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
+ if (cur == node2)
+ return(-1);
+ depth1++;
+ }
+ /*
+ * Distinct document (or distinct entities :-( ) case.
+ */
+ if (root != cur) {
+ return(-2);
+ }
+ /*
+ * get the nearest common ancestor.
+ */
+ while (depth1 > depth2) {
+ depth1--;
+ node1 = node1->parent;
+ }
+ while (depth2 > depth1) {
+ depth2--;
+ node2 = node2->parent;
+ }
+ while (node1->parent != node2->parent) {
+ node1 = node1->parent;
+ node2 = node2->parent;
+ /* should not happen but just in case ... */
+ if ((node1 == NULL) || (node2 == NULL))
+ return(-2);
+ }
+ /*
+ * Find who's first.
+ */
+ if (node1 == node2->next)
+ return(-1);
+ for (cur = node1->next;cur != NULL;cur = cur->next)
+ if (cur == node2)
+ return(1);
+ return(-1); /* assume there is no sibling list corruption */
+}
+
+/**
* xmlXPtrNewPoint:
* @node: the xmlNodePtr
* @index: the index within the node
@@ -85,6 +168,34 @@ xmlXPtrNewPoint(xmlNodePtr node, int index) {
}
/**
+ * xmlXPtrRangeCheckOrder:
+ * @range: an object range
+ *
+ * Make sure the points in the range are in the right order
+ */
+void
+xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) {
+ int tmp;
+ xmlNodePtr tmp2;
+ if (range == NULL)
+ return;
+ if (range->type != XPATH_RANGE)
+ return;
+ if (range->user2 == NULL)
+ return;
+ tmp = xmlXPtrCmpPoints(range->user, range->index,
+ range->user2, range->index2);
+ if (tmp == -1) {
+ tmp2 = range->user;
+ range->user = range->user2;
+ range->user2 = tmp2;
+ tmp = range->index;
+ range->index = range->index2;
+ range->index2 = tmp;
+ }
+}
+
+/**
* xmlXPtrNewRange:
* @start: the starting node
* @startindex: the start index
@@ -120,6 +231,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
ret->index = startindex;
ret->user2 = end;
ret->index2 = endindex;
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -156,6 +268,7 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
ret->index = start->index;
ret->user2 = end->user;
ret->index2 = end->index;
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -190,6 +303,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
ret->index = start->index;
ret->user2 = end;
ret->index2 = -1;
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -226,6 +340,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
ret->index = -1;
ret->user2 = end->user;
ret->index2 = end->index;
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -258,6 +373,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
ret->index = -1;
ret->user2 = end;
ret->index2 = -1;
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -344,6 +460,7 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
STRANGE
return(NULL);
}
+ xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -534,50 +651,6 @@ xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
xmlFree(obj);
}
-#if defined(DEBUG) || defined(DEBUG_STEP)
-/**
- * xmlXPtrDebugLocationSet:
- * @output: a FILE * for the output
- * @obj: the xmlLocationSetPtr to free
- *
- * Quick display of a LocationSet
- */
-void
-xmlXPtrDebugLocationSet(FILE *output, xmlLocationSetPtr obj) {
- int i;
-
- if (output == NULL) output = xmlXPathDebug;
- if (obj == NULL) {
- fprintf(output, "LocationSet == NULL !\n");
- return;
- }
- if (obj->locNr == 0) {
- fprintf(output, "LocationSet is empty\n");
- return;
- }
- if (obj->locTab == NULL) {
- fprintf(output, " locTab == NULL !\n");
- return;
- }
- for (i = 0; i < obj->locNr; i++) {
- if (obj->locTab[i] == NULL) {
- fprintf(output, " NULL !\n");
- return;
- }
- if ((obj->locTab[i]->type == XML_DOCUMENT_NODE) ||
- (obj->locTab[i]->type == XML_HTML_DOCUMENT_NODE))
- fprintf(output, " /");
- /******* TODO
- else if (obj->locTab[i]->name == NULL)
- fprintf(output, " noname!");
- else fprintf(output, " %s", obj->locTab[i]->name);
- ********/
- }
- fprintf(output, "\n");
-}
-#endif
-
-
/**
* xmlXPtrNewLocationSetNodes:
* @start: the start NodePtr value
@@ -1749,29 +1822,47 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
first = string[0];
stringlen = xmlStrlen(string);
- /* TODO: first = 0 */
while (cur != NULL) {
if (cur->content != NULL) {
len = xmlStrlen(cur->content);
while (pos <= len) {
- str = xmlStrchr(&cur->content[pos], first);
- if (str != NULL) {
- pos = (str - cur->content);
+ if (first != 0) {
+ str = xmlStrchr(&cur->content[pos], first);
+ if (str != NULL) {
+ pos = (str - cur->content);
#ifdef DEBUG_RANGES
- fprintf(stdout, "found '%c' at index %d of ->",
- first, pos + 1);
- xmlDebugDumpString(stdout, cur->content);
- fprintf(stdout, "\n");
+ fprintf(stdout, "found '%c' at index %d of ->",
+ first, pos + 1);
+ xmlDebugDumpString(stdout, cur->content);
+ fprintf(stdout, "\n");
#endif
- if (xmlXPtrMatchString(string, cur, pos + 1,
- end, endindex)) {
- *start = cur;
- *startindex = pos + 1;
- return(1);
+ if (xmlXPtrMatchString(string, cur, pos + 1,
+ end, endindex)) {
+ *start = cur;
+ *startindex = pos + 1;
+ return(1);
+ }
+ pos++;
+ } else {
+ pos = len + 1;
}
- pos++;
} else {
- pos = len + 1;
+ /*
+ * An empty string is considered to match before each
+ * character of the string-value and after the final
+ * character.
+ */
+#ifdef DEBUG_RANGES
+ fprintf(stdout, "found '' at index %d of ->",
+ pos + 1);
+ xmlDebugDumpString(stdout, cur->content);
+ fprintf(stdout, "\n");
+#endif
+ *start = cur;
+ *startindex = pos + 1;
+ *end = cur;
+ *endindex = pos + 1;
+ return(1);
}
}
}
@@ -2016,6 +2107,8 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPtrNewRange(start, startindex, fend, fendindex));
start = fend;
startindex = fendindex;
+ if (string->stringval[0] == 0)
+ startindex++;
}
} while (found == 1);
}