mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03: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:
@ -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>
|
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
|
* 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]))
|
Expression: xpointer(//chapter[position() = last()]/range-to(following::chapter[1]))
|
||||||
Object is empty (NULL)
|
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
|
TEXT
|
||||||
content=anced test
|
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>a diff<em>i</em>cult one</p>
|
||||||
<p><p>a span</p>n<p>ing one</p></p>
|
<p><p>a span</p>n<p>ing one</p></p>
|
||||||
<p><p>and an unbal</p><empty/>anced test</p>
|
<p><p>and an unbal</p><empty/>anced test</p>
|
||||||
|
<p>for empty string <seq>123</seq></p>
|
||||||
</chapter>
|
</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() <= 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() = 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, 'difficult'))
|
||||||
xpointer(string-range(//p, 'spanning'))
|
xpointer(string-range(//p, 'spanning'))
|
||||||
xpointer(string-range(//p, 'unbalanced'))
|
xpointer(string-range(//p, 'unbalanced'))
|
||||||
|
xpointer(string-range(//seq, ''))
|
||||||
|
6
xpath.c
6
xpath.c
@ -2692,7 +2692,7 @@ xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
void
|
void
|
||||||
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
CHECK_ARITY(0);
|
CHECK_ARITY(0);
|
||||||
if (ctxt->context->proximityPosition > 0) {
|
if (ctxt->context->proximityPosition >= 0) {
|
||||||
valuePush(ctxt,
|
valuePush(ctxt,
|
||||||
xmlXPathNewFloat((double) ctxt->context->proximityPosition));
|
xmlXPathNewFloat((double) ctxt->context->proximityPosition));
|
||||||
#ifdef DEBUG_EXPR
|
#ifdef DEBUG_EXPR
|
||||||
@ -4772,14 +4772,14 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
|
|||||||
ctxt->context->node = NULL;
|
ctxt->context->node = NULL;
|
||||||
|
|
||||||
if ((oldset == NULL) || (oldset->nodeNr == 0)) {
|
if ((oldset == NULL) || (oldset->nodeNr == 0)) {
|
||||||
xmlXPathEvalExpr(ctxt);
|
|
||||||
CHECK_ERROR;
|
|
||||||
ctxt->context->contextSize = 0;
|
ctxt->context->contextSize = 0;
|
||||||
ctxt->context->proximityPosition = 0;
|
ctxt->context->proximityPosition = 0;
|
||||||
|
xmlXPathEvalExpr(ctxt);
|
||||||
res = valuePop(ctxt);
|
res = valuePop(ctxt);
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
xmlXPathFreeObject(res);
|
xmlXPathFreeObject(res);
|
||||||
valuePush(ctxt, obj);
|
valuePush(ctxt, obj);
|
||||||
|
CHECK_ERROR;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Save the expression pointer since we will have to evaluate
|
* Save the expression pointer since we will have to evaluate
|
||||||
|
183
xpointer.c
183
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:
|
* xmlXPtrNewPoint:
|
||||||
* @node: the xmlNodePtr
|
* @node: the xmlNodePtr
|
||||||
@ -84,6 +167,34 @@ xmlXPtrNewPoint(xmlNodePtr node, int index) {
|
|||||||
return(ret);
|
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:
|
* xmlXPtrNewRange:
|
||||||
* @start: the starting node
|
* @start: the starting node
|
||||||
@ -120,6 +231,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
|
|||||||
ret->index = startindex;
|
ret->index = startindex;
|
||||||
ret->user2 = end;
|
ret->user2 = end;
|
||||||
ret->index2 = endindex;
|
ret->index2 = endindex;
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +268,7 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
|
|||||||
ret->index = start->index;
|
ret->index = start->index;
|
||||||
ret->user2 = end->user;
|
ret->user2 = end->user;
|
||||||
ret->index2 = end->index;
|
ret->index2 = end->index;
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +303,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
|
|||||||
ret->index = start->index;
|
ret->index = start->index;
|
||||||
ret->user2 = end;
|
ret->user2 = end;
|
||||||
ret->index2 = -1;
|
ret->index2 = -1;
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +340,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
|
|||||||
ret->index = -1;
|
ret->index = -1;
|
||||||
ret->user2 = end->user;
|
ret->user2 = end->user;
|
||||||
ret->index2 = end->index;
|
ret->index2 = end->index;
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +373,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
|
|||||||
ret->index = -1;
|
ret->index = -1;
|
||||||
ret->user2 = end;
|
ret->user2 = end;
|
||||||
ret->index2 = -1;
|
ret->index2 = -1;
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +460,7 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
|
|||||||
STRANGE
|
STRANGE
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
xmlXPtrRangeCheckOrder(ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,50 +651,6 @@ xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
|
|||||||
xmlFree(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:
|
* xmlXPtrNewLocationSetNodes:
|
||||||
* @start: the start NodePtr value
|
* @start: the start NodePtr value
|
||||||
@ -1749,11 +1822,11 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
|
|||||||
first = string[0];
|
first = string[0];
|
||||||
stringlen = xmlStrlen(string);
|
stringlen = xmlStrlen(string);
|
||||||
|
|
||||||
/* TODO: first = 0 */
|
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
if (cur->content != NULL) {
|
if (cur->content != NULL) {
|
||||||
len = xmlStrlen(cur->content);
|
len = xmlStrlen(cur->content);
|
||||||
while (pos <= len) {
|
while (pos <= len) {
|
||||||
|
if (first != 0) {
|
||||||
str = xmlStrchr(&cur->content[pos], first);
|
str = xmlStrchr(&cur->content[pos], first);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
pos = (str - cur->content);
|
pos = (str - cur->content);
|
||||||
@ -1773,6 +1846,24 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
|
|||||||
} else {
|
} else {
|
||||||
pos = len + 1;
|
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
|
||||||
|
*start = cur;
|
||||||
|
*startindex = pos + 1;
|
||||||
|
*end = cur;
|
||||||
|
*endindex = pos + 1;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((cur == *end) && (pos >= *endindex))
|
if ((cur == *end) && (pos >= *endindex))
|
||||||
@ -2016,6 +2107,8 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
xmlXPtrNewRange(start, startindex, fend, fendindex));
|
xmlXPtrNewRange(start, startindex, fend, fendindex));
|
||||||
start = fend;
|
start = fend;
|
||||||
startindex = fendindex;
|
startindex = fendindex;
|
||||||
|
if (string->stringval[0] == 0)
|
||||||
|
startindex++;
|
||||||
}
|
}
|
||||||
} while (found == 1);
|
} while (found == 1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user