mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03: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:
@ -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>
|
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
|
* doc/xmldtd.html doc/xml.html: following a short step by step
|
||||||
|
56
HTMLparser.c
56
HTMLparser.c
@ -855,13 +855,13 @@ htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
|
|||||||
}
|
}
|
||||||
if ((xmlStrEqual(newtag, BAD_CAST"body")) || (xmlStrEqual(newtag, BAD_CAST"head")))
|
if ((xmlStrEqual(newtag, BAD_CAST"body")) || (xmlStrEqual(newtag, BAD_CAST"head")))
|
||||||
return;
|
return;
|
||||||
if (ctxt->nameNr <= 1) {
|
if ((ctxt->nameNr <= 1) &&
|
||||||
if ((xmlStrEqual(newtag, BAD_CAST"script")) ||
|
((xmlStrEqual(newtag, BAD_CAST"script")) ||
|
||||||
(xmlStrEqual(newtag, BAD_CAST"style")) ||
|
(xmlStrEqual(newtag, BAD_CAST"style")) ||
|
||||||
(xmlStrEqual(newtag, BAD_CAST"meta")) ||
|
(xmlStrEqual(newtag, BAD_CAST"meta")) ||
|
||||||
(xmlStrEqual(newtag, BAD_CAST"link")) ||
|
(xmlStrEqual(newtag, BAD_CAST"link")) ||
|
||||||
(xmlStrEqual(newtag, BAD_CAST"title")) ||
|
(xmlStrEqual(newtag, BAD_CAST"title")) ||
|
||||||
(xmlStrEqual(newtag, BAD_CAST"base"))) {
|
(xmlStrEqual(newtag, BAD_CAST"base")))) {
|
||||||
/*
|
/*
|
||||||
* dropped OBJECT ... i you put it first BODY will be
|
* dropped OBJECT ... i you put it first BODY will be
|
||||||
* assumed !
|
* assumed !
|
||||||
@ -872,7 +872,19 @@ htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
|
|||||||
htmlnamePush(ctxt, xmlStrdup(BAD_CAST"head"));
|
htmlnamePush(ctxt, xmlStrdup(BAD_CAST"head"));
|
||||||
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
||||||
ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
|
ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
|
||||||
} else {
|
} 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
|
#ifdef DEBUG
|
||||||
xmlGenericError(xmlGenericErrorContext,"Implied element body: pushed body\n");
|
xmlGenericError(xmlGenericErrorContext,"Implied element body: pushed body\n");
|
||||||
#endif
|
#endif
|
||||||
@ -880,7 +892,6 @@ htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
|
|||||||
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
|
||||||
ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
|
ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2932,6 +2943,41 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
|
|||||||
*/
|
*/
|
||||||
htmlCheckImplied(ctxt, name);
|
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
|
* 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
|
# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
|
||||||
# the libltdl convenience library and INCLTDL to the include flags for
|
# the libltdl convenience library, adds --enable-ltdl-convenience to
|
||||||
# the libltdl header and adds --enable-ltdl-convenience to the
|
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||||
# configure arguments. Note that LIBLTDL and INCLTDL are not
|
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||||
# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
|
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||||
# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
|
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||||
# with '${top_builddir}/' and INCLTDL will be prefixed with
|
# flat, and, if you're not using automake, define top_builddir as
|
||||||
# '${top_srcdir}/' (note the single quotes!). If your package is not
|
# appropriate in the Makefiles.
|
||||||
# flat and you're not using automake, define top_builddir and
|
|
||||||
# top_srcdir appropriately in the Makefiles.
|
|
||||||
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||||
case "$enable_ltdl_convenience" in
|
case "$enable_ltdl_convenience" in
|
||||||
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
|
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
|
||||||
"") enable_ltdl_convenience=yes
|
"") enable_ltdl_convenience=yes
|
||||||
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
|
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
|
||||||
esac
|
esac
|
||||||
LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
|
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
|
||||||
INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
|
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||||
])
|
])
|
||||||
|
|
||||||
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
|
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
|
||||||
# the libltdl installable library and INCLTDL to the include flags for
|
# the libltdl installable library, and adds --enable-ltdl-install to
|
||||||
# the libltdl header and adds --enable-ltdl-install to the configure
|
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||||
# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
|
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||||
# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
|
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||||
# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
|
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||||
# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
|
# flat, and, if you're not using automake, define top_builddir as
|
||||||
# with '${top_srcdir}/' (note the single quotes!). If your package is
|
# appropriate in the Makefiles.
|
||||||
# not flat and you're not using automake, define top_builddir and
|
|
||||||
# top_srcdir appropriately in the Makefiles.
|
|
||||||
# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
|
# 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_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||||
AC_CHECK_LIB(ltdl, main,
|
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
|
if test x"$enable_ltdl_install" = x"yes"; then
|
||||||
ac_configure_args="$ac_configure_args --enable-ltdl-install"
|
ac_configure_args="$ac_configure_args --enable-ltdl-install"
|
||||||
LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
|
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
|
||||||
INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
|
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||||
else
|
else
|
||||||
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
|
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
|
||||||
LIBLTDL="-lltdl"
|
LIBLTDL="-lltdl"
|
||||||
|
@ -1686,9 +1686,9 @@ xmlIconvWrapper(iconv_t cd,
|
|||||||
#ifdef EINVAL
|
#ifdef EINVAL
|
||||||
if (errno == EINVAL) {
|
if (errno == EINVAL) {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
} else
|
||||||
#endif
|
#endif
|
||||||
else {
|
{
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,8 @@ void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
|||||||
* Existing functions
|
* Existing functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||||
|
xmlXPathObjectPtr res);
|
||||||
void xmlXPathInit(void);
|
void xmlXPathInit(void);
|
||||||
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
|
void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
|
||||||
|
@ -49,6 +49,7 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
|
|||||||
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
||||||
int nargs);
|
int nargs);
|
||||||
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
||||||
|
void xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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="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">
|
<meta content="MSHTML 5.00.3103.1000" name="GENERATOR">
|
||||||
</head>
|
</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">
|
<frame marginheight="0" marginwidth="0" name="left" noresize scrolling="no" src="doc2_files/side.htm" target="rtop">
|
||||||
<frameset rows="43,*">
|
<frameset rows="43,*">
|
||||||
<frame marginheight="0" marginwidth="0" name="rtop" noresize scrolling="no" src="doc2_files/top.htm" target="rbottom">
|
<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">
|
<frame name="rbottom" noresize src="doc2_files/contents.htm" target="_top">
|
||||||
</frameset>
|
</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>
|
<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>
|
</html>
|
||||||
|
@ -37,7 +37,6 @@ SAX.ignorableWhitespace(
|
|||||||
SAX.startElement(meta, content='MSHTML 5.00.3103.1000', name='GENERATOR')
|
SAX.startElement(meta, content='MSHTML 5.00.3103.1000', name='GENERATOR')
|
||||||
SAX.endElement(meta)
|
SAX.endElement(meta)
|
||||||
SAX.endElement(head)
|
SAX.endElement(head)
|
||||||
SAX.startElement(body)
|
|
||||||
SAX.startElement(frameset, border='false', cols='172,*', frameborder='0', framespacing='0')
|
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.startElement(frame, marginheight='0', marginwidth='0', name='left', noresize, scrolling='no', src='doc2_files/side.htm', target='rtop')
|
||||||
SAX.endElement(frame)
|
SAX.endElement(frame)
|
||||||
@ -64,7 +63,6 @@ SAX.characters(
|
|||||||
, 3)
|
, 3)
|
||||||
SAX.endElement(noframes)
|
SAX.endElement(noframes)
|
||||||
SAX.endElement(frameset)
|
SAX.endElement(frameset)
|
||||||
SAX.endElement(body)
|
|
||||||
SAX.endElement(html)
|
SAX.endElement(html)
|
||||||
SAX.ignorableWhitespace(
|
SAX.ignorableWhitespace(
|
||||||
, 1)
|
, 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])
|
12
xpath.c
12
xpath.c
@ -4421,12 +4421,16 @@ xmlXPathEvalFilterExpr(xmlXPathParserContextPtr ctxt) {
|
|||||||
CHECK_ERROR;
|
CHECK_ERROR;
|
||||||
SKIP_BLANKS;
|
SKIP_BLANKS;
|
||||||
|
|
||||||
if (CUR != '[') return;
|
|
||||||
|
|
||||||
CHECK_TYPE(XPATH_NODESET);
|
|
||||||
|
|
||||||
while (CUR == '[') {
|
while (CUR == '[') {
|
||||||
|
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);
|
xmlXPathEvalPredicate(ctxt);
|
||||||
|
else
|
||||||
|
xmlXPtrEvalRangePredicate(ctxt);
|
||||||
SKIP_BLANKS;
|
SKIP_BLANKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,8 @@ void xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
|
|||||||
* Existing functions
|
* Existing functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||||
|
xmlXPathObjectPtr res);
|
||||||
void xmlXPathInit(void);
|
void xmlXPathInit(void);
|
||||||
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
|
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:
|
* xmlXPtrNewRange:
|
||||||
* @start: the starting node
|
* @start: the starting node
|
||||||
@ -594,6 +624,7 @@ xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
|
|||||||
* @val: a new xmlXPathObjectPtr
|
* @val: a new xmlXPathObjectPtr
|
||||||
*
|
*
|
||||||
* add a new xmlXPathObjectPtr ot an existing LocationSet
|
* add a new xmlXPathObjectPtr ot an existing LocationSet
|
||||||
|
* If the location already exist in the set @val is freed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
||||||
@ -604,8 +635,12 @@ xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
|
|||||||
/*
|
/*
|
||||||
* check against doublons
|
* check against doublons
|
||||||
*/
|
*/
|
||||||
for (i = 0;i < cur->locNr;i++)
|
for (i = 0;i < cur->locNr;i++) {
|
||||||
if (cur->locTab[i] == val) return;
|
if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
|
||||||
|
xmlXPathFreeObject(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* grow the locTab if needed
|
* grow the locTab if needed
|
||||||
@ -1656,6 +1691,10 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newset = xmlXPtrLocationSetCreate(NULL);
|
newset = xmlXPtrLocationSetCreate(NULL);
|
||||||
|
if (newset == NULL) {
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
XP_ERROR(XPATH_MEMORY_ERROR);
|
||||||
|
}
|
||||||
oldset = (xmlLocationSetPtr) obj->user;
|
oldset = (xmlLocationSetPtr) obj->user;
|
||||||
if (oldset != NULL) {
|
if (oldset != NULL) {
|
||||||
int i;
|
int i;
|
||||||
@ -1680,10 +1719,6 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
point = xmlXPtrNewPoint(node, tmp->index);
|
point = xmlXPtrNewPoint(node, tmp->index);
|
||||||
}
|
}
|
||||||
if (tmp->user2 == NULL) {
|
|
||||||
point = xmlXPtrNewPoint(node, 0);
|
|
||||||
} else
|
|
||||||
point = xmlXPtrNewPoint(node, tmp->index);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1699,6 +1734,7 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1762,7 +1798,7 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
point = xmlXPtrNewPoint(tmp->user, tmp->index);
|
point = xmlXPtrNewPoint(tmp->user, tmp->index);
|
||||||
break;
|
break;
|
||||||
case XPATH_RANGE: {
|
case XPATH_RANGE: {
|
||||||
xmlNodePtr node = tmp->user;
|
xmlNodePtr node = tmp->user2;
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
if (node->type == XML_ATTRIBUTE_NODE) {
|
if (node->type == XML_ATTRIBUTE_NODE) {
|
||||||
/* TODO: Namespace Nodes ??? */
|
/* TODO: Namespace Nodes ??? */
|
||||||
@ -1770,13 +1806,11 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
xmlXPtrFreeLocationSet(newset);
|
xmlXPtrFreeLocationSet(newset);
|
||||||
XP_ERROR(XPTR_SYNTAX_ERROR);
|
XP_ERROR(XPTR_SYNTAX_ERROR);
|
||||||
}
|
}
|
||||||
point = xmlXPtrNewPoint(node, tmp->index);
|
point = xmlXPtrNewPoint(node, tmp->index2);
|
||||||
}
|
} else if (tmp->user == NULL) {
|
||||||
if (tmp->user2 == NULL) {
|
|
||||||
point = xmlXPtrNewPoint(node,
|
point = xmlXPtrNewPoint(node,
|
||||||
xmlXPtrNbLocChildren(node));
|
xmlXPtrNbLocChildren(node));
|
||||||
} else
|
}
|
||||||
point = xmlXPtrNewPoint(node, tmp->index);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1792,6 +1826,7 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2515,6 +2550,8 @@ xmlXPtrGetLastChar(xmlNodePtr *node, int *index) {
|
|||||||
len = xmlBufferLength(cur->content);
|
len = xmlBufferLength(cur->content);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cur == NULL)
|
if (cur == NULL)
|
||||||
@ -2756,6 +2793,115 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
if (number) xmlXPathFreeObject(number);
|
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
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
|
|||||||
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
|
||||||
int nargs);
|
int nargs);
|
||||||
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
xmlNodePtr xmlXPtrBuildNodeList (xmlXPathObjectPtr obj);
|
||||||
|
void xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user