mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00
More work on XPointer
- 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 Daniel
This commit is contained in:
parent
189446d2fa
commit
ff9c330753
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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]))
|
||||
|
@ -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, ''))
|
||||
|
8
xpath.c
8
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
|
||||
|
211
xpointer.c
211
xpointer.c
@ -54,6 +54,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
|
||||
@ -84,6 +167,34 @@ xmlXPtrNewPoint(xmlNodePtr node, int index) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -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);
|
||||
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);
|
||||
}
|
||||
pos++;
|
||||
} else {
|
||||
pos = len + 1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 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
|
||||
if (xmlXPtrMatchString(string, cur, pos + 1,
|
||||
end, endindex)) {
|
||||
*start = cur;
|
||||
*startindex = pos + 1;
|
||||
return(1);
|
||||
}
|
||||
pos++;
|
||||
} else {
|
||||
pos = len + 1;
|
||||
*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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user