mirror of
https://github.com/GNOME/libxml2.git
synced 2025-04-12 19:30:25 +08:00
General fixes, XPointer improvements:
- HTMLparser.c: some fixes on auto-open of html/head/body - encoding.c: fixed a compilation error on some gcc env - xpath.c xpointer.[ch] xpathInternals.h: improved the XPointer implementation - test/XPath/xptr/strpoint test/XPath/xptr/strrange3: added related XPointer tests and associated results Daniel
This commit is contained in:
parent
851c59c20e
commit
f62ceffb7e
@ -1,3 +1,12 @@
|
||||
Sat Nov 25 00:24:49 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||
|
||||
* HTMLparser.c: some fixes on auto-open of html/head/body
|
||||
* encoding.c: fixed a compilation error on some gcc env
|
||||
* xpath.c xpointer.[ch] xpathInternals.h: improved the
|
||||
XPointer implementation
|
||||
* test/XPath/xptr/strpoint test/XPath/xptr/strrange3: added
|
||||
related XPointer tests and associated results
|
||||
|
||||
Fri Nov 24 14:01:44 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||
|
||||
* doc/xmldtd.html doc/xml.html: following a short step by step
|
||||
|
74
HTMLparser.c
74
HTMLparser.c
@ -855,13 +855,13 @@ htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
|
||||
}
|
||||
if ((xmlStrEqual(newtag, BAD_CAST"body")) || (xmlStrEqual(newtag, BAD_CAST"head")))
|
||||
return;
|
||||
if (ctxt->nameNr <= 1) {
|
||||
if ((xmlStrEqual(newtag, BAD_CAST"script")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"style")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"meta")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"link")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"title")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"base"))) {
|
||||
if ((ctxt->nameNr <= 1) &&
|
||||
((xmlStrEqual(newtag, BAD_CAST"script")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"style")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"meta")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"link")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"title")) ||
|
||||
(xmlStrEqual(newtag, BAD_CAST"base")))) {
|
||||
/*
|
||||
* dropped OBJECT ... i you put it first BODY will be
|
||||
* assumed !
|
||||
@ -872,14 +872,25 @@ htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
|
||||
htmlnamePush(ctxt, xmlStrdup(BAD_CAST"head"));
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
||||
ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
xmlGenericError(xmlGenericErrorContext,"Implied element body: pushed body\n");
|
||||
#endif
|
||||
htmlnamePush(ctxt, xmlStrdup(BAD_CAST"body"));
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
||||
ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
|
||||
} else if ((!xmlStrEqual(newtag, BAD_CAST"noframes")) &&
|
||||
(!xmlStrEqual(newtag, BAD_CAST"frame")) &&
|
||||
(!xmlStrEqual(newtag, BAD_CAST"frameset"))) {
|
||||
int i;
|
||||
for (i = 0;i < ctxt->nameNr;i++) {
|
||||
if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"body")) {
|
||||
return;
|
||||
}
|
||||
if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"head")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
xmlGenericError(xmlGenericErrorContext,"Implied element body: pushed body\n");
|
||||
#endif
|
||||
htmlnamePush(ctxt, xmlStrdup(BAD_CAST"body"));
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
||||
ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2932,6 +2943,41 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
|
||||
*/
|
||||
htmlCheckImplied(ctxt, name);
|
||||
|
||||
/*
|
||||
* Avoid html at any level > 0, head at any level != 1
|
||||
* or any attempt to recurse body
|
||||
*/
|
||||
if ((ctxt->nameNr > 0) && (xmlStrEqual(name, BAD_CAST"html"))) {
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"htmlParseStartTag: misplaced <html> tag\n");
|
||||
ctxt->wellFormed = 0;
|
||||
xmlFree(name);
|
||||
return;
|
||||
}
|
||||
if ((ctxt->nameNr != 1) &&
|
||||
(xmlStrEqual(name, BAD_CAST"head"))) {
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"htmlParseStartTag: misplaced <head> tag\n");
|
||||
ctxt->wellFormed = 0;
|
||||
xmlFree(name);
|
||||
return;
|
||||
}
|
||||
if (xmlStrEqual(name, BAD_CAST"body")) {
|
||||
int i;
|
||||
for (i = 0;i < ctxt->nameNr;i++) {
|
||||
if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"body")) {
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"htmlParseStartTag: misplaced <body> tag\n");
|
||||
ctxt->wellFormed = 0;
|
||||
xmlFree(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now parse the attributes, it ends up with the ending
|
||||
*
|
||||
|
40
aclocal.m4
vendored
40
aclocal.m4
vendored
@ -620,35 +620,31 @@ esac
|
||||
])
|
||||
|
||||
# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
|
||||
# the libltdl convenience library and INCLTDL to the include flags for
|
||||
# the libltdl header and adds --enable-ltdl-convenience to the
|
||||
# configure arguments. Note that LIBLTDL and INCLTDL are not
|
||||
# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
|
||||
# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
|
||||
# with '${top_builddir}/' and INCLTDL will be prefixed with
|
||||
# '${top_srcdir}/' (note the single quotes!). If your package is not
|
||||
# flat and you're not using automake, define top_builddir and
|
||||
# top_srcdir appropriately in the Makefiles.
|
||||
# the libltdl convenience library, adds --enable-ltdl-convenience to
|
||||
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||
# flat, and, if you're not using automake, define top_builddir as
|
||||
# appropriate in the Makefiles.
|
||||
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
case "$enable_ltdl_convenience" in
|
||||
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
|
||||
"") enable_ltdl_convenience=yes
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
|
||||
esac
|
||||
LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
|
||||
INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
|
||||
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
|
||||
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||
])
|
||||
|
||||
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
|
||||
# the libltdl installable library and INCLTDL to the include flags for
|
||||
# the libltdl header and adds --enable-ltdl-install to the configure
|
||||
# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
|
||||
# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
|
||||
# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
|
||||
# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
|
||||
# with '${top_srcdir}/' (note the single quotes!). If your package is
|
||||
# not flat and you're not using automake, define top_builddir and
|
||||
# top_srcdir appropriately in the Makefiles.
|
||||
# the libltdl installable library, and adds --enable-ltdl-install to
|
||||
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||
# flat, and, if you're not using automake, define top_builddir as
|
||||
# appropriate in the Makefiles.
|
||||
# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
|
||||
AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
AC_CHECK_LIB(ltdl, main,
|
||||
@ -661,8 +657,8 @@ AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
])
|
||||
if test x"$enable_ltdl_install" = x"yes"; then
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-install"
|
||||
LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
|
||||
INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
|
||||
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
|
||||
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||
else
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
|
||||
LIBLTDL="-lltdl"
|
||||
|
@ -1686,9 +1686,9 @@ xmlIconvWrapper(iconv_t cd,
|
||||
#ifdef EINVAL
|
||||
if (errno == EINVAL) {
|
||||
return -3;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
else {
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +133,8 @@ void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
||||
* Existing functions
|
||||
*/
|
||||
|
||||
int xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||
xmlXPathObjectPtr res);
|
||||
void xmlXPathInit(void);
|
||||
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||
void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
|
||||
|
@ -49,6 +49,7 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
|
||||
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
||||
int nargs);
|
||||
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
||||
void xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -13,12 +13,12 @@
|
||||
<meta content="agent,technology,intranet,extranet,management,filtering,ranking,solution,service,intelligent,intelligence,client,server,architecture,developer,development,information,telecommunication,announcement,press,product,profile,contact,multi-agent,meta-search,metasearch,multi-thread,mobile,wireless,shopping,robot,PCS,Copernic,engine,toolkit,CDK,EDK" name="KEYWORDS">
|
||||
<meta content="MSHTML 5.00.3103.1000" name="GENERATOR">
|
||||
</head>
|
||||
<body><frameset border="false" cols="172,*" frameborder="0" framespacing="0">
|
||||
<frameset border="false" cols="172,*" frameborder="0" framespacing="0">
|
||||
<frame marginheight="0" marginwidth="0" name="left" noresize scrolling="no" src="doc2_files/side.htm" target="rtop">
|
||||
<frameset rows="43,*">
|
||||
<frame marginheight="0" marginwidth="0" name="rtop" noresize scrolling="no" src="doc2_files/top.htm" target="rbottom">
|
||||
<frame name="rbottom" noresize src="doc2_files/contents.htm" target="_top">
|
||||
</frameset>
|
||||
<noframes><body bgcolor="#FFFFFF" text="#000000" link="#000080" vlink="#000080" alink="#000080" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0"><p>This page uses frames, but your browser doesn't support them.</p></body></noframes>
|
||||
</frameset></body>
|
||||
</frameset>
|
||||
</html>
|
||||
|
@ -37,7 +37,6 @@ SAX.ignorableWhitespace(
|
||||
SAX.startElement(meta, content='MSHTML 5.00.3103.1000', name='GENERATOR')
|
||||
SAX.endElement(meta)
|
||||
SAX.endElement(head)
|
||||
SAX.startElement(body)
|
||||
SAX.startElement(frameset, border='false', cols='172,*', frameborder='0', framespacing='0')
|
||||
SAX.startElement(frame, marginheight='0', marginwidth='0', name='left', noresize, scrolling='no', src='doc2_files/side.htm', target='rtop')
|
||||
SAX.endElement(frame)
|
||||
@ -64,7 +63,6 @@ SAX.characters(
|
||||
, 3)
|
||||
SAX.endElement(noframes)
|
||||
SAX.endElement(frameset)
|
||||
SAX.endElement(body)
|
||||
SAX.endElement(html)
|
||||
SAX.ignorableWhitespace(
|
||||
, 1)
|
||||
|
75
result/XPath/xptr/strpoint
Normal file
75
result/XPath/xptr/strpoint
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
========================
|
||||
Expression: xpointer(start-point(string-range(//p,'multiple')))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 1 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(end-point(string-range(//p,'multiple')))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 8 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(start-point(string-range(//p,'test')))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 10 in node TEXT
|
||||
content=a simple test
|
||||
|
||||
2 : Object is a point : index 10 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
3 : Object is a point : index 7 in node TEXT
|
||||
content=anced test
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(end-point(string-range(//p,'test')))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 13 in node TEXT
|
||||
content=a simple test
|
||||
|
||||
2 : Object is a point : index 13 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
3 : Object is a point : index 10 in node TEXT
|
||||
content=anced test
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(start-point(string-range(//*,'multiple',1,0)))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 1 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(end-point(string-range(//*,'multiple',1,0)))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 1 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(start-point(string-range(//*,'multiple',1,1)))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 1 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(end-point(string-range(//*,'multiple',1,1)))
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 2 in node TEXT
|
||||
content=multiple tests
|
||||
|
||||
|
||||
========================
|
||||
Expression: xpointer(start-point(string-range(//p,'test'))[1])
|
||||
Object is a Location Set:
|
||||
1 : Object is a point : index 10 in node TEXT
|
||||
content=a simple test
|
||||
|
48
result/XPath/xptr/strrange3
Normal file
48
result/XPath/xptr/strrange3
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
========================
|
||||
Expression: xpointer(string-range(//p, 'test', 1, 0))
|
||||
Object is a Location Set:
|
||||
1 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=a simple test
|
||||
2 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=multiple tests
|
||||
3 : Object is a collapsed range :
|
||||
index 7 in node
|
||||
TEXT
|
||||
content=anced test
|
||||
|
||||
========================
|
||||
Expression: xpointer(string-range(//*, 'test', 1, 0))
|
||||
Object is a Location Set:
|
||||
1 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=a simple test
|
||||
2 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=multiple tests
|
||||
3 : Object is a collapsed range :
|
||||
index 7 in node
|
||||
TEXT
|
||||
content=anced test
|
||||
|
||||
========================
|
||||
Expression: xpointer(string-range(//p, 'test', 1, 0)[2])
|
||||
Object is a Location Set:
|
||||
1 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=multiple tests
|
||||
|
||||
========================
|
||||
Expression: xpointer(string-range(//*, 'test', 1, 0)[2])
|
||||
Object is a Location Set:
|
||||
1 : Object is a collapsed range :
|
||||
index 10 in node
|
||||
TEXT
|
||||
content=multiple tests
|
9
test/XPath/xptr/strpoint
Normal file
9
test/XPath/xptr/strpoint
Normal file
@ -0,0 +1,9 @@
|
||||
xpointer(start-point(string-range(//p,'multiple')))
|
||||
xpointer(end-point(string-range(//p,'multiple')))
|
||||
xpointer(start-point(string-range(//p,'test')))
|
||||
xpointer(end-point(string-range(//p,'test')))
|
||||
xpointer(start-point(string-range(//*,'multiple',1,0)))
|
||||
xpointer(end-point(string-range(//*,'multiple',1,0)))
|
||||
xpointer(start-point(string-range(//*,'multiple',1,1)))
|
||||
xpointer(end-point(string-range(//*,'multiple',1,1)))
|
||||
xpointer(start-point(string-range(//p,'test'))[1])
|
4
test/XPath/xptr/strrange3
Normal file
4
test/XPath/xptr/strrange3
Normal file
@ -0,0 +1,4 @@
|
||||
xpointer(string-range(//p, 'test', 1, 0))
|
||||
xpointer(string-range(//*, 'test', 1, 0))
|
||||
xpointer(string-range(//p, 'test', 1, 0)[2])
|
||||
xpointer(string-range(//*, 'test', 1, 0)[2])
|
14
xpath.c
14
xpath.c
@ -4421,12 +4421,16 @@ xmlXPathEvalFilterExpr(xmlXPathParserContextPtr ctxt) {
|
||||
CHECK_ERROR;
|
||||
SKIP_BLANKS;
|
||||
|
||||
if (CUR != '[') return;
|
||||
|
||||
CHECK_TYPE(XPATH_NODESET);
|
||||
|
||||
while (CUR == '[') {
|
||||
xmlXPathEvalPredicate(ctxt);
|
||||
if ((ctxt->value == NULL) ||
|
||||
((ctxt->value->type != XPATH_NODESET) &&
|
||||
(ctxt->value->type != XPATH_LOCATIONSET)))
|
||||
XP_ERROR(XPATH_INVALID_TYPE)
|
||||
|
||||
if (ctxt->value->type == XPATH_NODESET)
|
||||
xmlXPathEvalPredicate(ctxt);
|
||||
else
|
||||
xmlXPtrEvalRangePredicate(ctxt);
|
||||
SKIP_BLANKS;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,8 @@ void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
||||
* Existing functions
|
||||
*/
|
||||
|
||||
int xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||
xmlXPathObjectPtr res);
|
||||
void xmlXPathInit(void);
|
||||
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||
void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
|
||||
|
170
xpointer.c
170
xpointer.c
@ -275,6 +275,36 @@ xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPtrRangesEqual:
|
||||
* @range1: the first range
|
||||
* @range2: the second range
|
||||
*
|
||||
* Compare two ranges
|
||||
*
|
||||
* Return 1 if equal, 0 otherwise
|
||||
*/
|
||||
int
|
||||
xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
|
||||
if (range1 == range2)
|
||||
return(1);
|
||||
if ((range1 == NULL) || (range2 == NULL))
|
||||
return(0);
|
||||
if (range1->type != range2->type)
|
||||
return(0);
|
||||
if (range1->type != XPATH_RANGE)
|
||||
return(0);
|
||||
if (range1->user != range2->user)
|
||||
return(0);
|
||||
if (range1->index != range2->index)
|
||||
return(0);
|
||||
if (range1->user2 != range2->user2)
|
||||
return(0);
|
||||
if (range1->index2 != range2->index2)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPtrNewRange:
|
||||
* @start: the starting node
|
||||
@ -594,6 +624,7 @@ xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
|
||||
* @val: a new xmlXPathObjectPtr
|
||||
*
|
||||
* add a new xmlXPathObjectPtr ot an existing LocationSet
|
||||
* If the location already exist in the set @val is freed.
|
||||
*/
|
||||
void
|
||||
xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
||||
@ -604,8 +635,12 @@ xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
||||
/*
|
||||
* check against doublons
|
||||
*/
|
||||
for (i = 0;i < cur->locNr;i++)
|
||||
if (cur->locTab[i] == val) return;
|
||||
for (i = 0;i < cur->locNr;i++) {
|
||||
if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
|
||||
xmlXPathFreeObject(val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* grow the locTab if needed
|
||||
@ -1656,6 +1691,10 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
}
|
||||
|
||||
newset = xmlXPtrLocationSetCreate(NULL);
|
||||
if (newset == NULL) {
|
||||
xmlXPathFreeObject(obj);
|
||||
XP_ERROR(XPATH_MEMORY_ERROR);
|
||||
}
|
||||
oldset = (xmlLocationSetPtr) obj->user;
|
||||
if (oldset != NULL) {
|
||||
int i;
|
||||
@ -1680,10 +1719,6 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
}
|
||||
point = xmlXPtrNewPoint(node, tmp->index);
|
||||
}
|
||||
if (tmp->user2 == NULL) {
|
||||
point = xmlXPtrNewPoint(node, 0);
|
||||
} else
|
||||
point = xmlXPtrNewPoint(node, tmp->index);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1699,6 +1734,7 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(obj);
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1762,7 +1798,7 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
point = xmlXPtrNewPoint(tmp->user, tmp->index);
|
||||
break;
|
||||
case XPATH_RANGE: {
|
||||
xmlNodePtr node = tmp->user;
|
||||
xmlNodePtr node = tmp->user2;
|
||||
if (node != NULL) {
|
||||
if (node->type == XML_ATTRIBUTE_NODE) {
|
||||
/* TODO: Namespace Nodes ??? */
|
||||
@ -1770,13 +1806,11 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
xmlXPtrFreeLocationSet(newset);
|
||||
XP_ERROR(XPTR_SYNTAX_ERROR);
|
||||
}
|
||||
point = xmlXPtrNewPoint(node, tmp->index);
|
||||
}
|
||||
if (tmp->user2 == NULL) {
|
||||
point = xmlXPtrNewPoint(node, tmp->index2);
|
||||
} else if (tmp->user == NULL) {
|
||||
point = xmlXPtrNewPoint(node,
|
||||
xmlXPtrNbLocChildren(node));
|
||||
} else
|
||||
point = xmlXPtrNewPoint(node, tmp->index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1792,6 +1826,7 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(obj);
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||
}
|
||||
|
||||
|
||||
@ -2515,6 +2550,8 @@ xmlXPtrGetLastChar(xmlNodePtr *node, int *index) {
|
||||
len = xmlBufferLength(cur->content);
|
||||
#endif
|
||||
break;
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if (cur == NULL)
|
||||
@ -2756,6 +2793,115 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
if (number) xmlXPathFreeObject(number);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPtrEvalRangePredicate:
|
||||
* @ctxt: the XPointer Parser context
|
||||
*
|
||||
* [8] Predicate ::= '[' PredicateExpr ']'
|
||||
* [9] PredicateExpr ::= Expr
|
||||
*
|
||||
* Evaluate a predicate as in xmlXPathEvalPredicate() but for
|
||||
* a Location Set instead of a node set
|
||||
*/
|
||||
void
|
||||
xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) {
|
||||
const xmlChar *cur;
|
||||
xmlXPathObjectPtr res;
|
||||
xmlXPathObjectPtr obj, tmp;
|
||||
xmlLocationSetPtr newset = NULL;
|
||||
xmlLocationSetPtr oldset;
|
||||
int i;
|
||||
|
||||
SKIP_BLANKS;
|
||||
if (CUR != '[') {
|
||||
XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
|
||||
}
|
||||
NEXT;
|
||||
SKIP_BLANKS;
|
||||
|
||||
/*
|
||||
* Extract the old set, and then evaluate the result of the
|
||||
* expression for all the element in the set. use it to grow
|
||||
* up a new set.
|
||||
*/
|
||||
CHECK_TYPE(XPATH_LOCATIONSET);
|
||||
obj = valuePop(ctxt);
|
||||
oldset = obj->user;
|
||||
ctxt->context->node = NULL;
|
||||
|
||||
if ((oldset == NULL) || (oldset->locNr == 0)) {
|
||||
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
|
||||
* it multiple times. Initialize the new set.
|
||||
*/
|
||||
cur = ctxt->cur;
|
||||
newset = xmlXPtrLocationSetCreate(NULL);
|
||||
|
||||
for (i = 0; i < oldset->locNr; i++) {
|
||||
ctxt->cur = cur;
|
||||
|
||||
/*
|
||||
* Run the evaluation with a node list made of a single item
|
||||
* in the nodeset.
|
||||
*/
|
||||
ctxt->context->node = oldset->locTab[i]->user;
|
||||
tmp = xmlXPathNewNodeSet(ctxt->context->node);
|
||||
valuePush(ctxt, tmp);
|
||||
ctxt->context->contextSize = oldset->locNr;
|
||||
ctxt->context->proximityPosition = i + 1;
|
||||
|
||||
xmlXPathEvalExpr(ctxt);
|
||||
CHECK_ERROR;
|
||||
|
||||
/*
|
||||
* The result of the evaluation need to be tested to
|
||||
* decided whether the filter succeeded or not
|
||||
*/
|
||||
res = valuePop(ctxt);
|
||||
if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
|
||||
xmlXPtrLocationSetAdd(newset,
|
||||
xmlXPathObjectCopy(oldset->locTab[i]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup
|
||||
*/
|
||||
if (res != NULL)
|
||||
xmlXPathFreeObject(res);
|
||||
if (ctxt->value == tmp) {
|
||||
res = valuePop(ctxt);
|
||||
xmlXPathFreeObject(res);
|
||||
}
|
||||
|
||||
ctxt->context->node = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The result is used as the new evaluation set.
|
||||
*/
|
||||
xmlXPathFreeObject(obj);
|
||||
ctxt->context->node = NULL;
|
||||
ctxt->context->contextSize = -1;
|
||||
ctxt->context->proximityPosition = -1;
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||
}
|
||||
if (CUR != ']') {
|
||||
XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
|
||||
}
|
||||
|
||||
NEXT;
|
||||
SKIP_BLANKS;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
@ -49,6 +49,7 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
|
||||
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
||||
int nargs);
|
||||
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
||||
void xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user