mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-08-08 17:42:14 +03:00
Going forward in XPointer implementation:
- testXPath.c xpath.[ch]: moved some debug functions to xpath core - xpointer.c: implemented string-range() at least a good first version - test/XPath/docs/str test/XPath/xptr/strrange result/XPath/xptr/strrange: the string-range() tests Daniel
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
Fri Oct 13 02:54:37 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||||
|
|
||||||
|
* testXPath.c xpath.[ch]: moved some debug functions to xpath core
|
||||||
|
* xpointer.c: implemented string-range() at least a good first version
|
||||||
|
* test/XPath/docs/str test/XPath/xptr/strrange
|
||||||
|
result/XPath/xptr/strrange: the string-range() tests
|
||||||
|
|
||||||
Thu Oct 12 10:02:59 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
|
Thu Oct 12 10:02:59 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||||
|
|
||||||
* Makefile.am include/Makefile.am include/win32config.h
|
* Makefile.am include/Makefile.am include/win32config.h
|
||||||
|
@@ -345,6 +345,9 @@ dist-hook: libxml.spec
|
|||||||
-cp libxml.spec $(distdir)
|
-cp libxml.spec $(distdir)
|
||||||
(cd $(srcdir) ; tar -cf - --exclude CVS test result SAXresult ) | (cd $(distdir); tar xf -)
|
(cd $(srcdir) ; tar -cf - --exclude CVS test result SAXresult ) | (cd $(distdir); tar xf -)
|
||||||
|
|
||||||
|
rpm: $(distdir).tar.gz
|
||||||
|
rpm -ta $(distdir).tar.gz
|
||||||
|
|
||||||
## We create xmlConf.sh here and not from configure because we want
|
## We create xmlConf.sh here and not from configure because we want
|
||||||
## to get the paths expanded correctly. Macros like srcdir are given
|
## to get the paths expanded correctly. Macros like srcdir are given
|
||||||
## the value NONE in configure if the user doesn't specify them (this
|
## the value NONE in configure if the user doesn't specify them (this
|
||||||
|
@@ -178,19 +178,19 @@ struct _xmlXPathContext {
|
|||||||
|
|
||||||
int nb_variables; /* number of defined variables */
|
int nb_variables; /* number of defined variables */
|
||||||
int max_variables; /* max number of variables */
|
int max_variables; /* max number of variables */
|
||||||
xmlXPathVariablePtr *variables; /* Array of defined variables */
|
xmlXPathVariablePtr variables; /* Array of defined variables */
|
||||||
|
|
||||||
int nb_types; /* number of defined types */
|
int nb_types; /* number of defined types */
|
||||||
int max_types; /* max number of types */
|
int max_types; /* max number of types */
|
||||||
xmlXPathTypePtr *types; /* Array of defined types */
|
xmlXPathTypePtr types; /* Array of defined types */
|
||||||
|
|
||||||
int nb_funcs; /* number of defined funcs */
|
int nb_funcs; /* number of defined funcs */
|
||||||
int max_funcs; /* max number of funcs */
|
int max_funcs; /* max number of funcs */
|
||||||
xmlXPathFuncPtr *funcs; /* Array of defined funcs */
|
xmlXPathFuncPtr funcs; /* Array of defined funcs */
|
||||||
|
|
||||||
int nb_axis; /* number of defined axis */
|
int nb_axis; /* number of defined axis */
|
||||||
int max_axis; /* max number of axis */
|
int max_axis; /* max number of axis */
|
||||||
xmlXPathAxisPtr *axis; /* Array of defined axis */
|
xmlXPathAxisPtr axis; /* Array of defined axis */
|
||||||
|
|
||||||
/* Namespace traversal should be implemented with user */
|
/* Namespace traversal should be implemented with user */
|
||||||
xmlNsPtr *namespaces; /* The namespaces lookup */
|
xmlNsPtr *namespaces; /* The namespaces lookup */
|
||||||
@@ -266,6 +266,10 @@ void xmlXPatherror (xmlXPathParserContextPtr ctxt,
|
|||||||
int line,
|
int line,
|
||||||
int no);
|
int no);
|
||||||
|
|
||||||
|
void xmlXPathDebugDumpObject (FILE *output,
|
||||||
|
xmlXPathObjectPtr cur,
|
||||||
|
int depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities to extend XPath (XPointer)
|
* Utilities to extend XPath (XPointer)
|
||||||
*/
|
*/
|
||||||
|
76
result/XPath/xptr/strrange
Normal file
76
result/XPath/xptr/strrange
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
========================
|
||||||
|
Expression: xpointer(string-range(//p, 'simple'))
|
||||||
|
Object is a Location Set:
|
||||||
|
1 : Object is a range :
|
||||||
|
From index 3 in node
|
||||||
|
TEXT
|
||||||
|
content=a simple test
|
||||||
|
To index 8 in node
|
||||||
|
TEXT
|
||||||
|
content=a simple test
|
||||||
|
|
||||||
|
|
||||||
|
========================
|
||||||
|
Expression: xpointer(string-range(//p, 'test'))
|
||||||
|
Object is a Location Set:
|
||||||
|
1 : Object is a range :
|
||||||
|
From index 10 in node
|
||||||
|
TEXT
|
||||||
|
content=a simple test
|
||||||
|
To index 13 in node
|
||||||
|
TEXT
|
||||||
|
content=a simple test
|
||||||
|
|
||||||
|
2 : Object is a range :
|
||||||
|
From index 10 in node
|
||||||
|
TEXT
|
||||||
|
content=multiple tests
|
||||||
|
To index 13 in node
|
||||||
|
TEXT
|
||||||
|
content=multiple tests
|
||||||
|
|
||||||
|
3 : Object is a range :
|
||||||
|
From index 7 in node
|
||||||
|
TEXT
|
||||||
|
content=anced test
|
||||||
|
To index 10 in node
|
||||||
|
TEXT
|
||||||
|
content=anced test
|
||||||
|
|
||||||
|
|
||||||
|
========================
|
||||||
|
Expression: xpointer(string-range(//p, 'difficult'))
|
||||||
|
Object is a Location Set:
|
||||||
|
1 : Object is a range :
|
||||||
|
From index 3 in node
|
||||||
|
TEXT
|
||||||
|
content=a diff
|
||||||
|
To index 4 in node
|
||||||
|
TEXT
|
||||||
|
content=cult one
|
||||||
|
|
||||||
|
|
||||||
|
========================
|
||||||
|
Expression: xpointer(string-range(//p, 'spanning'))
|
||||||
|
Object is a Location Set:
|
||||||
|
1 : Object is a range :
|
||||||
|
From index 3 in node
|
||||||
|
TEXT
|
||||||
|
content=a span
|
||||||
|
To index 3 in node
|
||||||
|
TEXT
|
||||||
|
content=ing one
|
||||||
|
|
||||||
|
|
||||||
|
========================
|
||||||
|
Expression: xpointer(string-range(//p, 'unbalanced'))
|
||||||
|
Object is a Location Set:
|
||||||
|
1 : Object is a range :
|
||||||
|
From index 8 in node
|
||||||
|
TEXT
|
||||||
|
content=and an unbal
|
||||||
|
To index 5 in node
|
||||||
|
TEXT
|
||||||
|
content=anced test
|
||||||
|
|
8
test/XPath/docs/str
Normal file
8
test/XPath/docs/str
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<chapter>
|
||||||
|
<p>a simple test</p>
|
||||||
|
<p>multiple tests</p>
|
||||||
|
<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>
|
||||||
|
</chapter>
|
5
test/XPath/xptr/strrange
Normal file
5
test/XPath/xptr/strrange
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
xpointer(string-range(//p, 'simple'))
|
||||||
|
xpointer(string-range(//p, 'test'))
|
||||||
|
xpointer(string-range(//p, 'difficult'))
|
||||||
|
xpointer(string-range(//p, 'spanning'))
|
||||||
|
xpointer(string-range(//p, 'unbalanced'))
|
142
testXPath.c
142
testXPath.c
@@ -84,146 +84,6 @@ static xmlChar buffer[] =
|
|||||||
</EXAMPLE>\n\
|
</EXAMPLE>\n\
|
||||||
";
|
";
|
||||||
|
|
||||||
void xmlXPAthDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
|
|
||||||
int i;
|
|
||||||
char shift[100];
|
|
||||||
|
|
||||||
for (i = 0;((i < depth) && (i < 25));i++)
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = ' ';
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = 0;
|
|
||||||
if (cur == NULL) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "Node is NULL !\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cur->type == XML_DOCUMENT_NODE) ||
|
|
||||||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, " /\n");
|
|
||||||
} else if (cur->type == XML_ATTRIBUTE_NODE)
|
|
||||||
xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
|
|
||||||
else
|
|
||||||
xmlDebugDumpOneNode(output, cur, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void xmlXPAthDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
|
|
||||||
int i;
|
|
||||||
char shift[100];
|
|
||||||
|
|
||||||
for (i = 0;((i < depth) && (i < 25));i++)
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = ' ';
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = 0;
|
|
||||||
|
|
||||||
if (cur == NULL) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "NodeSet is NULL !\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
|
|
||||||
for (i = 0;i < cur->nodeNr;i++) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "%d", i + 1);
|
|
||||||
xmlXPAthDebugDumpNode(output, cur->nodeTab[i], depth + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(LIBXML_XPTR_ENABLED)
|
|
||||||
void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
|
||||||
void xmlXPAthDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
|
|
||||||
int i;
|
|
||||||
char shift[100];
|
|
||||||
|
|
||||||
for (i = 0;((i < depth) && (i < 25));i++)
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = ' ';
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = 0;
|
|
||||||
|
|
||||||
if (cur == NULL) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "LocationSet is NULL !\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0;i < cur->locNr;i++) {
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "%d : ", i + 1);
|
|
||||||
xmlXPAthDebugDumpObject(output, cur->locTab[i], depth + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
|
|
||||||
int i;
|
|
||||||
char shift[100];
|
|
||||||
|
|
||||||
for (i = 0;((i < depth) && (i < 25));i++)
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = ' ';
|
|
||||||
shift[2 * i] = shift[2 * i + 1] = 0;
|
|
||||||
|
|
||||||
fprintf(output, shift);
|
|
||||||
|
|
||||||
if (cur == NULL) {
|
|
||||||
fprintf(output, "Object is empty (NULL)\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch(cur->type) {
|
|
||||||
case XPATH_UNDEFINED:
|
|
||||||
fprintf(output, "Object is uninitialized\n");
|
|
||||||
break;
|
|
||||||
case XPATH_NODESET:
|
|
||||||
fprintf(output, "Object is a Node Set :\n");
|
|
||||||
xmlXPAthDebugDumpNodeSet(output, cur->nodesetval, depth);
|
|
||||||
break;
|
|
||||||
case XPATH_BOOLEAN:
|
|
||||||
fprintf(output, "Object is a Boolean : ");
|
|
||||||
if (cur->boolval) fprintf(output, "true\n");
|
|
||||||
else fprintf(output, "false\n");
|
|
||||||
break;
|
|
||||||
case XPATH_NUMBER:
|
|
||||||
fprintf(output, "Object is a number : %0g\n", cur->floatval);
|
|
||||||
break;
|
|
||||||
case XPATH_STRING:
|
|
||||||
fprintf(output, "Object is a string : ");
|
|
||||||
xmlDebugDumpString(output, cur->stringval);
|
|
||||||
fprintf(output, "\n");
|
|
||||||
break;
|
|
||||||
case XPATH_POINT:
|
|
||||||
fprintf(output, "Object is a point : index %d in node", cur->index);
|
|
||||||
xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
|
|
||||||
fprintf(output, "\n");
|
|
||||||
break;
|
|
||||||
case XPATH_RANGE:
|
|
||||||
fprintf(output, "Object is a range :\n");
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "From ");
|
|
||||||
if (cur->index >= 0)
|
|
||||||
fprintf(output, "index %d in ", cur->index);
|
|
||||||
fprintf(output, "node\n");
|
|
||||||
xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
|
|
||||||
fprintf(output, shift);
|
|
||||||
fprintf(output, "To ");
|
|
||||||
if (cur->index2 >= 0)
|
|
||||||
fprintf(output, "index %d in ", cur->index2);
|
|
||||||
fprintf(output, "node\n");
|
|
||||||
xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user2, depth + 1);
|
|
||||||
fprintf(output, "\n");
|
|
||||||
break;
|
|
||||||
case XPATH_LOCATIONSET:
|
|
||||||
#if defined(LIBXML_XPTR_ENABLED)
|
|
||||||
fprintf(output, "Object is a Location Set:\n");
|
|
||||||
xmlXPAthDebugDumpLocationSet(output,
|
|
||||||
(xmlLocationSetPtr) cur->user, depth);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case XPATH_USERS:
|
|
||||||
fprintf(output, "Object is user defined\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void testXPath(const char *str) {
|
void testXPath(const char *str) {
|
||||||
xmlXPathObjectPtr res;
|
xmlXPathObjectPtr res;
|
||||||
@@ -243,7 +103,7 @@ void testXPath(const char *str) {
|
|||||||
#if defined(LIBXML_XPTR_ENABLED)
|
#if defined(LIBXML_XPTR_ENABLED)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
xmlXPAthDebugDumpObject(stdout, res, 0);
|
xmlXPathDebugDumpObject(stdout, res, 0);
|
||||||
xmlXPathFreeObject(res);
|
xmlXPathFreeObject(res);
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
}
|
}
|
||||||
|
232
xpath.c
232
xpath.c
@@ -52,11 +52,17 @@
|
|||||||
#ifdef LIBXML_XPTR_ENABLED
|
#ifdef LIBXML_XPTR_ENABLED
|
||||||
#include <libxml/xpointer.h>
|
#include <libxml/xpointer.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LIBXML_DEBUG_ENABLED
|
||||||
|
#include <libxml/debugXML.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* #define DEBUG */
|
/* #define DEBUG */
|
||||||
/* #define DEBUG_STEP */
|
/* #define DEBUG_STEP */
|
||||||
/* #define DEBUG_EXPR */
|
/* #define DEBUG_EXPR */
|
||||||
|
|
||||||
|
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
double xmlXPathStringEvalNumber(const xmlChar *str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup stuff for floating point
|
* Setup stuff for floating point
|
||||||
* The lack of portability of this section of the libc is annoying !
|
* The lack of portability of this section of the libc is annoying !
|
||||||
@@ -159,17 +165,14 @@ xmlXPathInit(void) {
|
|||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *xmlXPathDebug = NULL;
|
|
||||||
|
|
||||||
double xmlXPathStringEvalNumber(const xmlChar *str);
|
|
||||||
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Parser stacks related functions and macros *
|
* Debugging related functions *
|
||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
FILE *xmlXPathDebug = NULL;
|
||||||
|
|
||||||
#define TODO \
|
#define TODO \
|
||||||
fprintf(xmlXPathDebug, "Unimplemented block at %s:%d\n", \
|
fprintf(xmlXPathDebug, "Unimplemented block at %s:%d\n", \
|
||||||
__FILE__, __LINE__);
|
__FILE__, __LINE__);
|
||||||
@@ -178,6 +181,171 @@ void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
|||||||
fprintf(xmlXPathDebug, "Internal error at %s:%d\n", \
|
fprintf(xmlXPathDebug, "Internal error at %s:%d\n", \
|
||||||
__FILE__, __LINE__);
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
#ifdef LIBXML_DEBUG_ENABLED
|
||||||
|
double xmlXPathStringEvalNumber(const xmlChar *str);
|
||||||
|
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
|
||||||
|
void xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
|
||||||
|
int i;
|
||||||
|
char shift[100];
|
||||||
|
|
||||||
|
for (i = 0;((i < depth) && (i < 25));i++)
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = ' ';
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = 0;
|
||||||
|
if (cur == NULL) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "Node is NULL !\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cur->type == XML_DOCUMENT_NODE) ||
|
||||||
|
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, " /\n");
|
||||||
|
} else if (cur->type == XML_ATTRIBUTE_NODE)
|
||||||
|
xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
|
||||||
|
else
|
||||||
|
xmlDebugDumpOneNode(output, cur, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
|
||||||
|
int i;
|
||||||
|
char shift[100];
|
||||||
|
|
||||||
|
for (i = 0;((i < depth) && (i < 25));i++)
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = ' ';
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = 0;
|
||||||
|
|
||||||
|
if (cur == NULL) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "NodeSet is NULL !\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
|
||||||
|
for (i = 0;i < cur->nodeNr;i++) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "%d", i + 1);
|
||||||
|
xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LIBXML_XPTR_ENABLED)
|
||||||
|
void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
||||||
|
void xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
|
||||||
|
int i;
|
||||||
|
char shift[100];
|
||||||
|
|
||||||
|
for (i = 0;((i < depth) && (i < 25));i++)
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = ' ';
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = 0;
|
||||||
|
|
||||||
|
if (cur == NULL) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "LocationSet is NULL !\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;i < cur->locNr;i++) {
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "%d : ", i + 1);
|
||||||
|
xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
|
||||||
|
int i;
|
||||||
|
char shift[100];
|
||||||
|
|
||||||
|
for (i = 0;((i < depth) && (i < 25));i++)
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = ' ';
|
||||||
|
shift[2 * i] = shift[2 * i + 1] = 0;
|
||||||
|
|
||||||
|
fprintf(output, shift);
|
||||||
|
|
||||||
|
if (cur == NULL) {
|
||||||
|
fprintf(output, "Object is empty (NULL)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(cur->type) {
|
||||||
|
case XPATH_UNDEFINED:
|
||||||
|
fprintf(output, "Object is uninitialized\n");
|
||||||
|
break;
|
||||||
|
case XPATH_NODESET:
|
||||||
|
fprintf(output, "Object is a Node Set :\n");
|
||||||
|
xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
|
||||||
|
break;
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
fprintf(output, "Object is a Boolean : ");
|
||||||
|
if (cur->boolval) fprintf(output, "true\n");
|
||||||
|
else fprintf(output, "false\n");
|
||||||
|
break;
|
||||||
|
case XPATH_NUMBER:
|
||||||
|
fprintf(output, "Object is a number : %0g\n", cur->floatval);
|
||||||
|
break;
|
||||||
|
case XPATH_STRING:
|
||||||
|
fprintf(output, "Object is a string : ");
|
||||||
|
xmlDebugDumpString(output, cur->stringval);
|
||||||
|
fprintf(output, "\n");
|
||||||
|
break;
|
||||||
|
case XPATH_POINT:
|
||||||
|
fprintf(output, "Object is a point : index %d in node", cur->index);
|
||||||
|
xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
|
||||||
|
fprintf(output, "\n");
|
||||||
|
break;
|
||||||
|
case XPATH_RANGE:
|
||||||
|
if ((cur->user2 == NULL) ||
|
||||||
|
((cur->user2 == cur->user) && (cur->index == cur->index2))) {
|
||||||
|
fprintf(output, "Object is a collapsed range :\n");
|
||||||
|
fprintf(output, shift);
|
||||||
|
if (cur->index >= 0)
|
||||||
|
fprintf(output, "index %d in ", cur->index);
|
||||||
|
fprintf(output, "node\n");
|
||||||
|
xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
|
||||||
|
depth + 1);
|
||||||
|
} else {
|
||||||
|
fprintf(output, "Object is a range :\n");
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "From ");
|
||||||
|
if (cur->index >= 0)
|
||||||
|
fprintf(output, "index %d in ", cur->index);
|
||||||
|
fprintf(output, "node\n");
|
||||||
|
xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
|
||||||
|
depth + 1);
|
||||||
|
fprintf(output, shift);
|
||||||
|
fprintf(output, "To ");
|
||||||
|
if (cur->index2 >= 0)
|
||||||
|
fprintf(output, "index %d in ", cur->index2);
|
||||||
|
fprintf(output, "node\n");
|
||||||
|
xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
|
||||||
|
depth + 1);
|
||||||
|
fprintf(output, "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XPATH_LOCATIONSET:
|
||||||
|
#if defined(LIBXML_XPTR_ENABLED)
|
||||||
|
fprintf(output, "Object is a Location Set:\n");
|
||||||
|
xmlXPathDebugDumpLocationSet(output,
|
||||||
|
(xmlLocationSetPtr) cur->user, depth);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case XPATH_USERS:
|
||||||
|
fprintf(output, "Object is user defined\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Parser stacks related functions and macros *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic function for accessing stacks in the Parser Context
|
* Generic function for accessing stacks in the Parser Context
|
||||||
*/
|
*/
|
||||||
@@ -672,30 +840,31 @@ xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
|
|||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_funcs;i++) {
|
for (i = 0;i < ctxt->nb_funcs;i++) {
|
||||||
if (xmlStrEqual(ctxt->funcs[i]->name, name)) {
|
if (xmlStrEqual(ctxt->funcs[i].name, name)) {
|
||||||
/*
|
/*
|
||||||
* It's just an update or a removal
|
* It's just an update or a removal
|
||||||
*/
|
*/
|
||||||
ctxt->funcs[i]->func = f;
|
ctxt->funcs[i].func = f;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctxt->max_funcs <= 0) {
|
if (ctxt->max_funcs <= 0) {
|
||||||
ctxt->max_funcs = 10;
|
ctxt->max_funcs = 10;
|
||||||
ctxt->nb_funcs = 0;
|
ctxt->nb_funcs = 0;
|
||||||
ctxt->funcs = (xmlXPathFuncPtr *) xmlMalloc(ctxt->max_funcs *
|
ctxt->funcs = (xmlXPathFuncPtr) xmlMalloc(ctxt->max_funcs *
|
||||||
sizeof(xmlXPathFuncPtr));
|
sizeof(xmlXPathFunct));
|
||||||
} else if (ctxt->max_funcs <= ctxt->nb_funcs) {
|
} else if (ctxt->max_funcs <= ctxt->nb_funcs) {
|
||||||
ctxt->max_funcs *= 2;
|
ctxt->max_funcs *= 2;
|
||||||
ctxt->funcs = (xmlXPathFuncPtr *) xmlRealloc(ctxt->funcs,
|
ctxt->funcs = (xmlXPathFuncPtr) xmlRealloc(ctxt->funcs,
|
||||||
ctxt->max_funcs * sizeof(xmlXPathFuncPtr));
|
ctxt->max_funcs * sizeof(xmlXPathFunct));
|
||||||
}
|
}
|
||||||
if (ctxt->funcs == NULL) {
|
if (ctxt->funcs == NULL) {
|
||||||
fprintf(xmlXPathDebug, "xmlXPathRegisterFunc: out of memory\n");
|
fprintf(xmlXPathDebug, "xmlXPathRegisterFunc: out of memory\n");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->funcs[i]->name = xmlStrdup(name);
|
ctxt->funcs[ctxt->nb_funcs].name = xmlStrdup(name);
|
||||||
ctxt->funcs[i]->func = f;
|
ctxt->funcs[ctxt->nb_funcs].func = f;
|
||||||
|
ctxt->nb_funcs++;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,8 +888,8 @@ xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_funcs;i++) {
|
for (i = 0;i < ctxt->nb_funcs;i++) {
|
||||||
if (xmlStrEqual(ctxt->funcs[i]->name, name)) {
|
if (xmlStrEqual(ctxt->funcs[i].name, name)) {
|
||||||
return(ctxt->funcs[i]->func);
|
return(ctxt->funcs[i].func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
@@ -740,7 +909,7 @@ xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_funcs;i++) {
|
for (i = 0;i < ctxt->nb_funcs;i++) {
|
||||||
xmlFree((xmlChar *) ctxt->funcs[i]->name);
|
xmlFree((xmlChar *) ctxt->funcs[i].name);
|
||||||
}
|
}
|
||||||
ctxt->nb_funcs = -1;
|
ctxt->nb_funcs = -1;
|
||||||
ctxt->max_funcs = -1;
|
ctxt->max_funcs = -1;
|
||||||
@@ -777,34 +946,35 @@ xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
|
|||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_variables;i++) {
|
for (i = 0;i < ctxt->nb_variables;i++) {
|
||||||
if (xmlStrEqual(ctxt->variables[i]->name, name)) {
|
if (xmlStrEqual(ctxt->variables[i].name, name)) {
|
||||||
/*
|
/*
|
||||||
* It's just an update or a removal
|
* It's just an update or a removal
|
||||||
*/
|
*/
|
||||||
if (ctxt->variables[i]->value != NULL) {
|
if (ctxt->variables[i].value != NULL) {
|
||||||
xmlXPathFreeObject(ctxt->variables[i]->value);
|
xmlXPathFreeObject(ctxt->variables[i].value);
|
||||||
}
|
}
|
||||||
ctxt->variables[i]->value = xmlXPathObjectCopy(value);
|
ctxt->variables[i].value = xmlXPathObjectCopy(value);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctxt->max_variables <= 0) {
|
if (ctxt->max_variables <= 0) {
|
||||||
ctxt->max_variables = 10;
|
ctxt->max_variables = 10;
|
||||||
ctxt->nb_variables = 0;
|
ctxt->nb_variables = 0;
|
||||||
ctxt->variables = (xmlXPathVariablePtr *)
|
ctxt->variables = (xmlXPathVariablePtr)
|
||||||
xmlMalloc(ctxt->max_variables * sizeof(xmlXPathVariablePtr));
|
xmlMalloc(ctxt->max_variables * sizeof(xmlXPathVariable));
|
||||||
} else if (ctxt->max_variables <= ctxt->nb_variables) {
|
} else if (ctxt->max_variables <= ctxt->nb_variables) {
|
||||||
ctxt->max_variables *= 2;
|
ctxt->max_variables *= 2;
|
||||||
ctxt->variables = (xmlXPathVariablePtr *)
|
ctxt->variables = (xmlXPathVariablePtr)
|
||||||
xmlRealloc(ctxt->variables,
|
xmlRealloc(ctxt->variables,
|
||||||
ctxt->max_variables * sizeof(xmlXPathVariablePtr));
|
ctxt->max_variables * sizeof(xmlXPathVariable));
|
||||||
}
|
}
|
||||||
if (ctxt->variables == NULL) {
|
if (ctxt->variables == NULL) {
|
||||||
fprintf(xmlXPathDebug, "xmlXPathRegisterVariable: out of memory\n");
|
fprintf(xmlXPathDebug, "xmlXPathRegisterVariable: out of memory\n");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->variables[i]->name = xmlStrdup(name);
|
ctxt->variables[ctxt->nb_variables].name = xmlStrdup(name);
|
||||||
ctxt->variables[i]->value = xmlXPathObjectCopy(value);
|
ctxt->variables[ctxt->nb_variables].value = xmlXPathObjectCopy(value);
|
||||||
|
ctxt->nb_variables++;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,8 +998,8 @@ xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_variables;i++) {
|
for (i = 0;i < ctxt->nb_variables;i++) {
|
||||||
if (xmlStrEqual(ctxt->variables[i]->name, name)) {
|
if (xmlStrEqual(ctxt->variables[i].name, name)) {
|
||||||
return(xmlXPathObjectCopy(ctxt->variables[i]->value));
|
return(xmlXPathObjectCopy(ctxt->variables[i].value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
@@ -849,8 +1019,8 @@ xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0;i < ctxt->nb_variables;i++) {
|
for (i = 0;i < ctxt->nb_variables;i++) {
|
||||||
xmlFree((xmlChar *) ctxt->variables[i]->name);
|
xmlFree((xmlChar *) ctxt->variables[i].name);
|
||||||
xmlXPathFreeObject(ctxt->variables[i]->value);
|
xmlXPathFreeObject(ctxt->variables[i].value);
|
||||||
}
|
}
|
||||||
ctxt->nb_variables = -1;
|
ctxt->nb_variables = -1;
|
||||||
ctxt->max_variables = -1;
|
ctxt->max_variables = -1;
|
||||||
|
12
xpath.h
12
xpath.h
@@ -178,19 +178,19 @@ struct _xmlXPathContext {
|
|||||||
|
|
||||||
int nb_variables; /* number of defined variables */
|
int nb_variables; /* number of defined variables */
|
||||||
int max_variables; /* max number of variables */
|
int max_variables; /* max number of variables */
|
||||||
xmlXPathVariablePtr *variables; /* Array of defined variables */
|
xmlXPathVariablePtr variables; /* Array of defined variables */
|
||||||
|
|
||||||
int nb_types; /* number of defined types */
|
int nb_types; /* number of defined types */
|
||||||
int max_types; /* max number of types */
|
int max_types; /* max number of types */
|
||||||
xmlXPathTypePtr *types; /* Array of defined types */
|
xmlXPathTypePtr types; /* Array of defined types */
|
||||||
|
|
||||||
int nb_funcs; /* number of defined funcs */
|
int nb_funcs; /* number of defined funcs */
|
||||||
int max_funcs; /* max number of funcs */
|
int max_funcs; /* max number of funcs */
|
||||||
xmlXPathFuncPtr *funcs; /* Array of defined funcs */
|
xmlXPathFuncPtr funcs; /* Array of defined funcs */
|
||||||
|
|
||||||
int nb_axis; /* number of defined axis */
|
int nb_axis; /* number of defined axis */
|
||||||
int max_axis; /* max number of axis */
|
int max_axis; /* max number of axis */
|
||||||
xmlXPathAxisPtr *axis; /* Array of defined axis */
|
xmlXPathAxisPtr axis; /* Array of defined axis */
|
||||||
|
|
||||||
/* Namespace traversal should be implemented with user */
|
/* Namespace traversal should be implemented with user */
|
||||||
xmlNsPtr *namespaces; /* The namespaces lookup */
|
xmlNsPtr *namespaces; /* The namespaces lookup */
|
||||||
@@ -266,6 +266,10 @@ void xmlXPatherror (xmlXPathParserContextPtr ctxt,
|
|||||||
int line,
|
int line,
|
||||||
int no);
|
int no);
|
||||||
|
|
||||||
|
void xmlXPathDebugDumpObject (FILE *output,
|
||||||
|
xmlXPathObjectPtr cur,
|
||||||
|
int depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities to extend XPath (XPointer)
|
* Utilities to extend XPath (XPointer)
|
||||||
*/
|
*/
|
||||||
|
682
xpointer.c
682
xpointer.c
@@ -18,6 +18,10 @@
|
|||||||
/**
|
/**
|
||||||
* TODO: better handling of error cases, the full expression should
|
* TODO: better handling of error cases, the full expression should
|
||||||
* be parsed beforehand instead of a progressive evaluation
|
* be parsed beforehand instead of a progressive evaluation
|
||||||
|
* TODO: Access into entities references are not supported now ...
|
||||||
|
* need a start to be able to pop out of entities refs since
|
||||||
|
* parent is the endity declaration, not the ref.
|
||||||
|
* TODO: some functions are still missing !
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -25,8 +29,15 @@
|
|||||||
#include <libxml/xmlmemory.h>
|
#include <libxml/xmlmemory.h>
|
||||||
#include <libxml/parserInternals.h>
|
#include <libxml/parserInternals.h>
|
||||||
#include <libxml/xpath.h>
|
#include <libxml/xpath.h>
|
||||||
|
#ifdef LIBXML_DEBUG_ENABLED
|
||||||
|
#include <libxml/debugXML.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LIBXML_XPTR_ENABLED
|
#ifdef LIBXML_XPTR_ENABLED
|
||||||
|
|
||||||
|
/* #define DEBUG_RANGES */
|
||||||
|
|
||||||
|
|
||||||
extern FILE *xmlXPathDebug;
|
extern FILE *xmlXPathDebug;
|
||||||
|
|
||||||
#define TODO \
|
#define TODO \
|
||||||
@@ -73,6 +84,45 @@ xmlXPtrNewPoint(xmlNodePtr node, int index) {
|
|||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrNewRange:
|
||||||
|
* @start: the starting node
|
||||||
|
* @startindex: the start index
|
||||||
|
* @end: the ending point
|
||||||
|
* @endindex: the ending index
|
||||||
|
*
|
||||||
|
* Create a new xmlXPathObjectPtr of type range
|
||||||
|
*
|
||||||
|
* Returns the newly created object.
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr
|
||||||
|
xmlXPtrNewRange(xmlNodePtr start, int startindex,
|
||||||
|
xmlNodePtr end, int endindex) {
|
||||||
|
xmlXPathObjectPtr ret;
|
||||||
|
|
||||||
|
if (start == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if (end == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if (startindex < 0)
|
||||||
|
return(NULL);
|
||||||
|
if (endindex < 0)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
|
||||||
|
if (ret == NULL) {
|
||||||
|
fprintf(xmlXPathDebug, "xmlXPtrNewRangePoints: out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
|
||||||
|
ret->type = XPATH_RANGE;
|
||||||
|
ret->user = start;
|
||||||
|
ret->index = startindex;
|
||||||
|
ret->user2 = end;
|
||||||
|
ret->index2 = endindex;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrNewRangePoints:
|
* xmlXPtrNewRangePoints:
|
||||||
* @start: the starting point
|
* @start: the starting point
|
||||||
@@ -381,11 +431,10 @@ xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrLocationSetMerge:
|
* xmlXPtrLocationSetMerge:
|
||||||
* @val1: the first LocationSet or NULL
|
* @val1: the first LocationSet
|
||||||
* @val2: the second LocationSet
|
* @val2: the second LocationSet
|
||||||
*
|
*
|
||||||
* Merges two rangesets, all ranges from @val2 are added to @val1
|
* Merges two rangesets, all ranges from @val2 are added to @val1
|
||||||
* if @val1 is NULL, a new set is created and copied from @val2
|
|
||||||
*
|
*
|
||||||
* Returns val1 once extended or NULL in case of error.
|
* Returns val1 once extended or NULL in case of error.
|
||||||
*/
|
*/
|
||||||
@@ -393,12 +442,8 @@ xmlLocationSetPtr
|
|||||||
xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) {
|
xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (val1 == NULL) return(NULL);
|
||||||
if (val2 == NULL) return(val1);
|
if (val2 == NULL) return(val1);
|
||||||
if (val1 == NULL) {
|
|
||||||
val1 = xmlXPtrLocationSetCreate(NULL);
|
|
||||||
if (val1 == NULL)
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* !!!!! this can be optimized a lot, knowing that both
|
* !!!!! this can be optimized a lot, knowing that both
|
||||||
@@ -661,6 +706,33 @@ xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
|
|||||||
#define CURRENT (*ctxt->cur)
|
#define CURRENT (*ctxt->cur)
|
||||||
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
|
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrGetNthChild:
|
||||||
|
* @cur: the node
|
||||||
|
* @no: the child number
|
||||||
|
*
|
||||||
|
* Returns the @no'th element child of @cur or NULL
|
||||||
|
*/
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
|
||||||
|
int i;
|
||||||
|
if (cur == NULL)
|
||||||
|
return(cur);
|
||||||
|
cur = cur->children;
|
||||||
|
for (i = 0;i <= no;cur = cur->next) {
|
||||||
|
if (cur == NULL)
|
||||||
|
return(cur);
|
||||||
|
if ((cur->type == XML_ELEMENT_NODE) ||
|
||||||
|
(cur->type == XML_DOCUMENT_NODE) ||
|
||||||
|
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
||||||
|
i++;
|
||||||
|
if (i == no)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xmlXPtrGetChildNo:
|
* xmlXPtrGetChildNo:
|
||||||
* @ctxt: the XPointer Parser context
|
* @ctxt: the XPointer Parser context
|
||||||
@@ -674,7 +746,6 @@ xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int index) {
|
|||||||
xmlNodePtr cur = NULL;
|
xmlNodePtr cur = NULL;
|
||||||
xmlXPathObjectPtr obj;
|
xmlXPathObjectPtr obj;
|
||||||
xmlNodeSetPtr oldset;
|
xmlNodeSetPtr oldset;
|
||||||
int i;
|
|
||||||
|
|
||||||
CHECK_TYPE(XPATH_NODESET);
|
CHECK_TYPE(XPATH_NODESET);
|
||||||
obj = valuePop(ctxt);
|
obj = valuePop(ctxt);
|
||||||
@@ -684,23 +755,7 @@ xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int index) {
|
|||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cur = oldset->nodeTab[0];
|
cur = xmlXPtrGetNthChild(oldset->nodeTab[0], index);
|
||||||
if (cur == NULL)
|
|
||||||
goto done;
|
|
||||||
cur = cur->children;
|
|
||||||
for (i = 0;i <= index;cur = cur->next) {
|
|
||||||
if (cur == NULL)
|
|
||||||
goto done;
|
|
||||||
if ((cur->type == XML_ELEMENT_NODE) ||
|
|
||||||
(cur->type == XML_DOCUMENT_NODE) ||
|
|
||||||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
|
||||||
i++;
|
|
||||||
if (i == index)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (cur == NULL) {
|
if (cur == NULL) {
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
@@ -802,13 +857,9 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
|
|||||||
|
|
||||||
if (xmlStrEqual(name, (xmlChar *) "xpointer")) {
|
if (xmlStrEqual(name, (xmlChar *) "xpointer")) {
|
||||||
const xmlChar *left = CUR_PTR;
|
const xmlChar *left = CUR_PTR;
|
||||||
xmlXPathObjectPtr root = NULL;
|
|
||||||
|
|
||||||
CUR_PTR = buffer;
|
CUR_PTR = buffer;
|
||||||
if (buffer[0] == '/') {
|
|
||||||
xmlXPathRoot(ctxt);
|
xmlXPathRoot(ctxt);
|
||||||
root = ctxt->value;
|
|
||||||
}
|
|
||||||
xmlXPathEvalExpr(ctxt);
|
xmlXPathEvalExpr(ctxt);
|
||||||
CUR_PTR=left;
|
CUR_PTR=left;
|
||||||
} else {
|
} else {
|
||||||
@@ -986,6 +1037,13 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
|
|||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
void xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrNewContext:
|
* xmlXPtrNewContext:
|
||||||
* @doc: the XML document
|
* @doc: the XML document
|
||||||
@@ -1008,6 +1066,19 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
|
|||||||
ret->here = here;
|
ret->here = here;
|
||||||
ret->origin = origin;
|
ret->origin = origin;
|
||||||
|
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)"range-to",
|
||||||
|
xmlXPtrRangeToFunction);
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)"string-range",
|
||||||
|
xmlXPtrStringRangeFunction);
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)"start-point",
|
||||||
|
xmlXPtrStartPointFunction);
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)"end-point",
|
||||||
|
xmlXPtrEndPointFunction);
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)"here",
|
||||||
|
xmlXPtrHereFunction);
|
||||||
|
xmlXPathRegisterFunc(ret, (xmlChar *)" origin",
|
||||||
|
xmlXPtrOriginFunction);
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1054,9 +1125,20 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
|
|||||||
do {
|
do {
|
||||||
tmp = valuePop(ctxt);
|
tmp = valuePop(ctxt);
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
xmlXPathFreeObject(tmp);
|
if (tmp != init) {
|
||||||
if (tmp != init)
|
if (tmp->type == XPATH_NODESET) {
|
||||||
|
/*
|
||||||
|
* Evaluation may push a root nodeset which is unused
|
||||||
|
*/
|
||||||
|
xmlNodeSetPtr set;
|
||||||
|
set = tmp->nodesetval;
|
||||||
|
if ((set->nodeNr != 1) ||
|
||||||
|
(set->nodeTab[0] != (xmlNodePtr) ctx->doc))
|
||||||
stack++;
|
stack++;
|
||||||
|
} else
|
||||||
|
stack++;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
}
|
}
|
||||||
} while (tmp != NULL);
|
} while (tmp != NULL);
|
||||||
if (stack != 0) {
|
if (stack != 0) {
|
||||||
@@ -1125,14 +1207,14 @@ xmlXPtrNbLocChildren(xmlNodePtr node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrHere:
|
* xmlXPtrHereFunction:
|
||||||
* @ctxt: the XPointer Parser context
|
* @ctxt: the XPointer Parser context
|
||||||
*
|
*
|
||||||
* Function implementing here() operation
|
* Function implementing here() operation
|
||||||
* as described in 5.4.3
|
* as described in 5.4.3
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlXPtrHere(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
if (ctxt->context->here == NULL)
|
if (ctxt->context->here == NULL)
|
||||||
XP_ERROR(XPTR_SYNTAX_ERROR);
|
XP_ERROR(XPTR_SYNTAX_ERROR);
|
||||||
|
|
||||||
@@ -1140,14 +1222,14 @@ xmlXPtrHere(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrOrigin:
|
* xmlXPtrOriginFunction:
|
||||||
* @ctxt: the XPointer Parser context
|
* @ctxt: the XPointer Parser context
|
||||||
*
|
*
|
||||||
* Function implementing origin() operation
|
* Function implementing origin() operation
|
||||||
* as described in 5.4.3
|
* as described in 5.4.3
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlXPtrOrigin(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
if (ctxt->context->origin == NULL)
|
if (ctxt->context->origin == NULL)
|
||||||
XP_ERROR(XPTR_SYNTAX_ERROR);
|
XP_ERROR(XPTR_SYNTAX_ERROR);
|
||||||
|
|
||||||
@@ -1155,7 +1237,7 @@ xmlXPtrOrigin(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrStartPoint:
|
* xmlXPtrStartPointFunction:
|
||||||
* @ctxt: the XPointer Parser context
|
* @ctxt: the XPointer Parser context
|
||||||
*
|
*
|
||||||
* Function implementing start-point() operation
|
* Function implementing start-point() operation
|
||||||
@@ -1177,7 +1259,7 @@ xmlXPtrOrigin(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlXPtrStartPoint(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
xmlXPathObjectPtr tmp, obj, point;
|
xmlXPathObjectPtr tmp, obj, point;
|
||||||
xmlLocationSetPtr newset = NULL;
|
xmlLocationSetPtr newset = NULL;
|
||||||
xmlLocationSetPtr oldset = NULL;
|
xmlLocationSetPtr oldset = NULL;
|
||||||
@@ -1245,7 +1327,7 @@ xmlXPtrStartPoint(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPtrEndPoint:
|
* xmlXPtrEndPointFunction:
|
||||||
* @ctxt: the XPointer Parser context
|
* @ctxt: the XPointer Parser context
|
||||||
*
|
*
|
||||||
* Function implementing end-point() operation
|
* Function implementing end-point() operation
|
||||||
@@ -1269,7 +1351,7 @@ xmlXPtrStartPoint(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
* ----------------------------
|
* ----------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlXPtrEndPoint(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
xmlXPathObjectPtr tmp, obj, point;
|
xmlXPathObjectPtr tmp, obj, point;
|
||||||
xmlLocationSetPtr newset = NULL;
|
xmlLocationSetPtr newset = NULL;
|
||||||
xmlLocationSetPtr oldset = NULL;
|
xmlLocationSetPtr oldset = NULL;
|
||||||
@@ -1426,6 +1508,528 @@ xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrAdvanceNode:
|
||||||
|
* @cur: the node
|
||||||
|
*
|
||||||
|
* Advance to the next element or text node in document order
|
||||||
|
* TODO: add a stack for entering/exiting entities
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXPtrAdvanceNode(xmlNodePtr cur) {
|
||||||
|
next:
|
||||||
|
if (cur == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if (cur->children != NULL) {
|
||||||
|
cur = cur->children ;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
if (cur->next != NULL) {
|
||||||
|
cur = cur->next;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
cur = cur->parent;
|
||||||
|
if (cur == NULL) return(NULL);
|
||||||
|
if (cur->next != NULL) {
|
||||||
|
cur = cur->next;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
} while (cur != NULL);
|
||||||
|
|
||||||
|
found:
|
||||||
|
if ((cur->type != XML_ELEMENT_NODE) &&
|
||||||
|
(cur->type != XML_TEXT_NODE) &&
|
||||||
|
(cur->type != XML_DOCUMENT_NODE) &&
|
||||||
|
(cur->type != XML_HTML_DOCUMENT_NODE) &&
|
||||||
|
(cur->type != XML_CDATA_SECTION_NODE))
|
||||||
|
goto next;
|
||||||
|
if (cur->type == XML_ENTITY_REF_NODE) {
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrAdvanceChar:
|
||||||
|
* @node: the node
|
||||||
|
* @index: the index
|
||||||
|
* @bytes: the number of bytes
|
||||||
|
*
|
||||||
|
* Advance a point of the associated number of bytes (not UTF8 chars)
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrAdvanceChar(xmlNodePtr *node, int *index, int bytes) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
int pos;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if ((node == NULL) || (index == NULL))
|
||||||
|
return(-1);
|
||||||
|
cur = *node;
|
||||||
|
if (cur == NULL)
|
||||||
|
return(-1);
|
||||||
|
pos = *index;
|
||||||
|
|
||||||
|
while (bytes >= 0) {
|
||||||
|
/*
|
||||||
|
* First position to the beginning of the first text node
|
||||||
|
* corresponding to this point
|
||||||
|
*/
|
||||||
|
while ((cur != NULL) &&
|
||||||
|
((cur->type == XML_ELEMENT_NODE) ||
|
||||||
|
(cur->type == XML_DOCUMENT_NODE) ||
|
||||||
|
(cur->type == XML_HTML_DOCUMENT_NODE))) {
|
||||||
|
if (pos > 0) {
|
||||||
|
cur = xmlXPtrGetNthChild(cur, pos);
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
cur = xmlXPtrAdvanceNode(cur);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur == NULL) {
|
||||||
|
*node = NULL;
|
||||||
|
*index = 0;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is no move needed return the current value.
|
||||||
|
*/
|
||||||
|
if (pos == 0) pos = 1;
|
||||||
|
if (bytes == 0) {
|
||||||
|
*node = cur;
|
||||||
|
*index = pos;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* We should have a text (or cdata) node ...
|
||||||
|
*/
|
||||||
|
len = 0;
|
||||||
|
if (cur->content != NULL) {
|
||||||
|
len = xmlStrlen(cur->content);
|
||||||
|
}
|
||||||
|
if (pos > len) {
|
||||||
|
/* Strange, the index in the text node is greater than it's len */
|
||||||
|
STRANGE
|
||||||
|
pos = len;
|
||||||
|
}
|
||||||
|
if (pos + bytes >= len) {
|
||||||
|
bytes -= (len - pos);
|
||||||
|
cur = xmlXPtrAdvanceNode(cur);
|
||||||
|
cur = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrMatchString:
|
||||||
|
* @string: the string to search
|
||||||
|
* @start: the start textnode
|
||||||
|
* @startindex: the start index
|
||||||
|
* @end: the end textnode IN/OUT
|
||||||
|
* @endindex: the end index IN/OUT
|
||||||
|
*
|
||||||
|
* Check whether the document contains @string at the position
|
||||||
|
* (@start, @startindex) and limited by the (@end, @endindex) point
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 if not found, 1 if found in which case
|
||||||
|
* (@start, @startindex) will indicate the position of the beginning
|
||||||
|
* of the range and (@end, @endindex) will endicate the end
|
||||||
|
* of the range
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
|
||||||
|
xmlNodePtr *end, int *endindex) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
int pos; /* 0 based */
|
||||||
|
int len; /* in bytes */
|
||||||
|
int stringlen; /* in bytes */
|
||||||
|
int match;
|
||||||
|
|
||||||
|
if (string == NULL)
|
||||||
|
return(-1);
|
||||||
|
if (start == NULL)
|
||||||
|
return(-1);
|
||||||
|
if ((end == NULL) || (endindex == NULL))
|
||||||
|
return(-1);
|
||||||
|
cur = start;
|
||||||
|
if (cur == NULL)
|
||||||
|
return(-1);
|
||||||
|
pos = startindex - 1;
|
||||||
|
stringlen = xmlStrlen(string);
|
||||||
|
|
||||||
|
while (stringlen > 0) {
|
||||||
|
if ((cur == *end) && (pos + stringlen > *endindex))
|
||||||
|
return(0);
|
||||||
|
if (cur->content != NULL) {
|
||||||
|
len = xmlStrlen(cur->content);
|
||||||
|
if (len >= pos + stringlen) {
|
||||||
|
match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
|
||||||
|
if (match) {
|
||||||
|
#ifdef DEBUG_RANGES
|
||||||
|
fprintf(stdout, "found range %d bytes at index %d of ->",
|
||||||
|
stringlen, pos + 1);
|
||||||
|
xmlDebugDumpString(stdout, cur->content);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
#endif
|
||||||
|
*end = cur;
|
||||||
|
*endindex = pos + stringlen;
|
||||||
|
return(1);
|
||||||
|
} else {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int sub = len - pos;
|
||||||
|
match = (!xmlStrncmp(&cur->content[pos], string, sub));
|
||||||
|
if (match) {
|
||||||
|
#ifdef DEBUG_RANGES
|
||||||
|
fprintf(stdout, "found subrange %d bytes at index %d of ->",
|
||||||
|
sub, pos + 1);
|
||||||
|
xmlDebugDumpString(stdout, cur->content);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
#endif
|
||||||
|
string = &string[sub];
|
||||||
|
stringlen -= sub;
|
||||||
|
} else {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur = xmlXPtrAdvanceNode(cur);
|
||||||
|
if (cur == NULL)
|
||||||
|
return(0);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrSearchString:
|
||||||
|
* @string: the string to search
|
||||||
|
* @start: the start textnode IN/OUT
|
||||||
|
* @startindex: the start index IN/OUT
|
||||||
|
* @end: the end textnode
|
||||||
|
* @endindex: the end index
|
||||||
|
*
|
||||||
|
* Search the next occurence of @string within the document content
|
||||||
|
* until the (@end, @endindex) point is reached
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 if not found, 1 if found in which case
|
||||||
|
* (@start, @startindex) will indicate the position of the beginning
|
||||||
|
* of the range and (@end, @endindex) will endicate the end
|
||||||
|
* of the range
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
|
||||||
|
xmlNodePtr *end, int *endindex) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
const xmlChar *str;
|
||||||
|
int pos; /* 0 based */
|
||||||
|
int len; /* in bytes */
|
||||||
|
int stringlen; /* in bytes */
|
||||||
|
xmlChar first;
|
||||||
|
|
||||||
|
if (string == NULL)
|
||||||
|
return(-1);
|
||||||
|
if ((start == NULL) || (startindex == NULL))
|
||||||
|
return(-1);
|
||||||
|
if ((end == NULL) || (endindex == NULL))
|
||||||
|
return(-1);
|
||||||
|
cur = *start;
|
||||||
|
if (cur == NULL)
|
||||||
|
return(-1);
|
||||||
|
pos = *startindex - 1;
|
||||||
|
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);
|
||||||
|
#ifdef DEBUG_RANGES
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((cur == *end) && (pos >= *endindex))
|
||||||
|
return(0);
|
||||||
|
cur = xmlXPtrAdvanceNode(cur);
|
||||||
|
if (cur == NULL)
|
||||||
|
return(0);
|
||||||
|
pos = 1;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrGetLastChar:
|
||||||
|
* @node: the node
|
||||||
|
* @index: the index
|
||||||
|
*
|
||||||
|
* Computes the point coordinates of the last char of this point
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrGetLastChar(xmlNodePtr *node, int *index) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
int pos, len = 0;
|
||||||
|
|
||||||
|
if ((node == NULL) || (index == NULL))
|
||||||
|
return(-1);
|
||||||
|
cur = *node;
|
||||||
|
pos = *index;
|
||||||
|
|
||||||
|
if (cur == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if ((cur->type == XML_ELEMENT_NODE) ||
|
||||||
|
(cur->type == XML_DOCUMENT_NODE) ||
|
||||||
|
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
||||||
|
if (pos > 0) {
|
||||||
|
cur = xmlXPtrGetNthChild(cur, pos);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->last != NULL)
|
||||||
|
cur = cur->last;
|
||||||
|
else if (cur->content != NULL) {
|
||||||
|
len = xmlStrlen(cur->content);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur == NULL)
|
||||||
|
return(-1);
|
||||||
|
*node = cur;
|
||||||
|
*index = len;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrGetStartPoint:
|
||||||
|
* @obj: an range
|
||||||
|
* @node: the resulting node
|
||||||
|
* @index: the resulting index
|
||||||
|
*
|
||||||
|
* read the object and return the start point coordinates.
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrGetStartPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *index) {
|
||||||
|
if ((obj == NULL) || (node == NULL) || (index == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case XPATH_POINT:
|
||||||
|
*node = obj->user;
|
||||||
|
if (obj->index <= 0)
|
||||||
|
*index = 0;
|
||||||
|
else
|
||||||
|
*index = obj->index;
|
||||||
|
return(0);
|
||||||
|
case XPATH_RANGE:
|
||||||
|
*node = obj->user;
|
||||||
|
if (obj->index <= 0)
|
||||||
|
*index = 0;
|
||||||
|
else
|
||||||
|
*index = obj->index;
|
||||||
|
return(0);
|
||||||
|
default:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrGetEndPoint:
|
||||||
|
* @obj: an range
|
||||||
|
* @node: the resulting node
|
||||||
|
* @index: the resulting index
|
||||||
|
*
|
||||||
|
* read the object and return the end point coordinates.
|
||||||
|
*
|
||||||
|
* Returns -1 in case of failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPtrGetEndPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *index) {
|
||||||
|
if ((obj == NULL) || (node == NULL) || (index == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case XPATH_POINT:
|
||||||
|
*node = obj->user;
|
||||||
|
if (obj->index <= 0)
|
||||||
|
*index = 0;
|
||||||
|
else
|
||||||
|
*index = obj->index;
|
||||||
|
return(0);
|
||||||
|
case XPATH_RANGE:
|
||||||
|
*node = obj->user;
|
||||||
|
if (obj->index <= 0)
|
||||||
|
*index = 0;
|
||||||
|
else
|
||||||
|
*index = obj->index;
|
||||||
|
return(0);
|
||||||
|
default:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPtrStringRangeFunction:
|
||||||
|
* @ctxt: the XPointer Parser context
|
||||||
|
*
|
||||||
|
* Function implementing the string-range() function
|
||||||
|
* range as described in 5.4.2
|
||||||
|
*
|
||||||
|
* ------------------------------
|
||||||
|
* [Definition: For each location in the location-set argument,
|
||||||
|
* string-range returns a set of string ranges, a set of substrings in a
|
||||||
|
* string. Specifically, the string-value of the location is searched for
|
||||||
|
* substrings that match the string argument, and the resulting location-set
|
||||||
|
* will contain a range location for each non-overlapping match.]
|
||||||
|
* An empty string is considered to match before each character of the
|
||||||
|
* string-value and after the final character. Whitespace in a string
|
||||||
|
* is matched literally, with no normalization except that provided by
|
||||||
|
* XML for line ends. The third argument gives the position of the first
|
||||||
|
* character to be in the resulting range, relative to the start of the
|
||||||
|
* match. The default value is 1, which makes the range start immediately
|
||||||
|
* before the first character of the matched string. The fourth argument
|
||||||
|
* gives the number of characters in the range; the default is that the
|
||||||
|
* range extends to the end of the matched string.
|
||||||
|
*
|
||||||
|
* Element boundaries, as well as entire embedded nodes such as processing
|
||||||
|
* instructions and comments, are ignored as defined in [XPath].
|
||||||
|
*
|
||||||
|
* If the string in the second argument is not found in the string-value
|
||||||
|
* of the location, or if a value in the third or fourth argument indicates
|
||||||
|
* a string that is beyond the beginning or end of the document, the
|
||||||
|
* expression fails.
|
||||||
|
*
|
||||||
|
* The points of the range-locations in the returned location-set will
|
||||||
|
* all be character points.
|
||||||
|
* ------------------------------
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
|
int i, startindex, endindex, fendindex;
|
||||||
|
xmlNodePtr start, end, fend;
|
||||||
|
xmlXPathObjectPtr set;
|
||||||
|
xmlLocationSetPtr oldset;
|
||||||
|
xmlLocationSetPtr newset;
|
||||||
|
xmlXPathObjectPtr string;
|
||||||
|
xmlXPathObjectPtr position = NULL;
|
||||||
|
xmlXPathObjectPtr number = NULL;
|
||||||
|
int found;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grab the arguments
|
||||||
|
*/
|
||||||
|
if ((nargs < 2) || (nargs > 4))
|
||||||
|
XP_ERROR(XPATH_INVALID_ARITY);
|
||||||
|
|
||||||
|
if (nargs >= 4) {
|
||||||
|
CHECK_TYPE(XPATH_NUMBER);
|
||||||
|
number = valuePop(ctxt);
|
||||||
|
}
|
||||||
|
if (nargs >= 3) {
|
||||||
|
CHECK_TYPE(XPATH_NUMBER);
|
||||||
|
position = valuePop(ctxt);
|
||||||
|
}
|
||||||
|
CHECK_TYPE(XPATH_STRING);
|
||||||
|
string = valuePop(ctxt);
|
||||||
|
if ((ctxt->value == NULL) ||
|
||||||
|
((ctxt->value->type != XPATH_LOCATIONSET) &&
|
||||||
|
(ctxt->value->type != XPATH_NODESET)))
|
||||||
|
XP_ERROR(XPATH_INVALID_TYPE)
|
||||||
|
|
||||||
|
set = valuePop(ctxt);
|
||||||
|
if (set->type == XPATH_NODESET) {
|
||||||
|
xmlXPathObjectPtr tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First convert to a location set
|
||||||
|
*/
|
||||||
|
tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
|
||||||
|
xmlXPathFreeObject(set);
|
||||||
|
set = tmp;
|
||||||
|
}
|
||||||
|
oldset = (xmlLocationSetPtr) set->user;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The loop is to search for each element in the location set
|
||||||
|
* the list of location set corresponding to that search
|
||||||
|
*/
|
||||||
|
newset = xmlXPtrLocationSetCreate(NULL);
|
||||||
|
for (i = 0;i < oldset->locNr;i++) {
|
||||||
|
#ifdef DEBUG_RANGES
|
||||||
|
xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex);
|
||||||
|
xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex);
|
||||||
|
xmlXPtrAdvanceChar(&start, &startindex, 0);
|
||||||
|
xmlXPtrGetLastChar(&end, &endindex);
|
||||||
|
|
||||||
|
#ifdef DEBUG_RANGES
|
||||||
|
fprintf(stdout, "from index %d of ->", startindex);
|
||||||
|
xmlDebugDumpString(stdout, start->content);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "to index %d of ->", endindex);
|
||||||
|
xmlDebugDumpString(stdout, end->content);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
fend = end;
|
||||||
|
fendindex = endindex;
|
||||||
|
found = xmlXPtrSearchString(string->stringval, &start, &startindex,
|
||||||
|
&fend, &fendindex);
|
||||||
|
if (found == 1) {
|
||||||
|
xmlXPtrLocationSetAdd(newset,
|
||||||
|
xmlXPtrNewRange(start, startindex, fend, fendindex));
|
||||||
|
start = fend;
|
||||||
|
startindex = fendindex;
|
||||||
|
}
|
||||||
|
} while (found == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the new value and cleanup
|
||||||
|
*/
|
||||||
|
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||||
|
xmlXPathFreeObject(set);
|
||||||
|
xmlXPathFreeObject(string);
|
||||||
|
if (position) xmlXPathFreeObject(position);
|
||||||
|
if (number) xmlXPathFreeObject(number);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user