diff --git a/include/libxml/parser.h b/include/libxml/parser.h index 17051d79..ee4c8087 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -407,6 +407,9 @@ xmlDtdPtr xmlParseDTD (const xmlChar *ExternalID, xmlDtdPtr xmlSAXParseDTD (xmlSAXHandlerPtr sax, const xmlChar *ExternalID, const xmlChar *SystemID); +xmlDtdPtr xmlIOParseDTD (xmlSAXHandlerPtr sax, + xmlParserInputBufferPtr input, + xmlCharEncoding enc); int xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, diff --git a/parser.c b/parser.c index 7a932854..425ef57c 100644 --- a/parser.c +++ b/parser.c @@ -8360,6 +8360,90 @@ xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data, * * ************************************************************************/ +/** + * xmlIOParseDTD: + * @sax: the SAX handler block or NULL + * @input: an Input Buffer + * @enc: the charset encoding if known + * + * Load and parse a DTD + * + * Returns the resulting xmlDtdPtr or NULL in case of error. + */ + +xmlDtdPtr +xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, + xmlCharEncoding enc) { + xmlDtdPtr ret = NULL; + xmlParserCtxtPtr ctxt; + xmlParserInputPtr pinput = NULL; + + if (input == NULL) + return(NULL); + + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) { + return(NULL); + } + + /* + * Set-up the SAX context + */ + if (sax != NULL) { + if (ctxt->sax != NULL) + xmlFree(ctxt->sax); + ctxt->sax = sax; + ctxt->userData = NULL; + } + + /* + * generate a parser input from the I/O handler + */ + + pinput = xmlNewIOInputStream(ctxt, input, enc); + if (pinput == NULL) { + if (sax != NULL) ctxt->sax = NULL; + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + /* + * plug some encoding conversion routines here. + */ + xmlPushInput(ctxt, pinput); + + pinput->filename = NULL; + pinput->line = 1; + pinput->col = 1; + pinput->base = ctxt->input->cur; + pinput->cur = ctxt->input->cur; + pinput->free = NULL; + + /* + * let's parse that entity knowing it's an external subset. + */ + ctxt->inSubset = 2; + ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); + ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", + BAD_CAST "none", BAD_CAST "none"); + xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none"); + + if (ctxt->myDoc != NULL) { + if (ctxt->wellFormed) { + ret = ctxt->myDoc->extSubset; + ctxt->myDoc->extSubset = NULL; + } else { + ret = NULL; + } + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; + } + if (sax != NULL) ctxt->sax = NULL; + xmlFreeParserCtxt(ctxt); + + return(ret); +} + /** * xmlSAXParseDTD: * @sax: the SAX handler block diff --git a/parser.h b/parser.h index 17051d79..ee4c8087 100644 --- a/parser.h +++ b/parser.h @@ -407,6 +407,9 @@ xmlDtdPtr xmlParseDTD (const xmlChar *ExternalID, xmlDtdPtr xmlSAXParseDTD (xmlSAXHandlerPtr sax, const xmlChar *ExternalID, const xmlChar *SystemID); +xmlDtdPtr xmlIOParseDTD (xmlSAXHandlerPtr sax, + xmlParserInputBufferPtr input, + xmlCharEncoding enc); int xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, diff --git a/result/XPath/xptr/strrange2 b/result/XPath/xptr/strrange2 new file mode 100644 index 00000000..ea6ee45a --- /dev/null +++ b/result/XPath/xptr/strrange2 @@ -0,0 +1,64 @@ + +======================== +Expression: xpointer(string-range(//p, 'test', 2)) +Object is a Location Set: +1 : Object is a range : + From index 11 in node + TEXT + content=a simple test + To index 13 in node + TEXT + content=a simple test + +2 : Object is a range : + From index 11 in node + TEXT + content=multiple tests + To index 13 in node + TEXT + content=multiple tests + +3 : Object is a range : + From index 8 in node + TEXT + content=anced test + To index 10 in node + TEXT + content=anced test + + +======================== +Expression: xpointer(string-range(//p, 'test', 2, 2)) +Object is a Location Set: +1 : Object is a range : + From index 11 in node + TEXT + content=a simple test + To index 12 in node + TEXT + content=a simple test + +2 : Object is a range : + From index 11 in node + TEXT + content=multiple tests + To index 12 in node + TEXT + content=multiple tests + +3 : Object is a range : + From index 8 in node + TEXT + content=anced test + To index 9 in node + TEXT + content=anced test + + +======================== +Expression: xpointer(string-range(//p, 'difficult', 1, 0)) +Object is a Location Set: +1 : Object is a collapsed range : + index 3 in node + TEXT + content=a diff diff --git a/test/XPath/xptr/strrange2 b/test/XPath/xptr/strrange2 new file mode 100644 index 00000000..51335470 --- /dev/null +++ b/test/XPath/xptr/strrange2 @@ -0,0 +1,3 @@ +xpointer(string-range(//p, 'test', 2)) +xpointer(string-range(//p, 'test', 2, 2)) +xpointer(string-range(//p, 'difficult', 1, 0)) diff --git a/xpointer.c b/xpointer.c index 77cf10e0..aa4b8e07 100644 --- a/xpointer.c +++ b/xpointer.c @@ -964,7 +964,7 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) { } cur = buffer; - while (CUR != '0') { + while (CUR != 0) { if (CUR == ')') { level--; if (level == 0) { @@ -1989,6 +1989,7 @@ xmlXPtrAdvanceChar(xmlNodePtr *node, int *index, int bytes) { pos = 0; } } + if (cur == NULL) { *node = NULL; *index = 0; @@ -2020,6 +2021,11 @@ xmlXPtrAdvanceChar(xmlNodePtr *node, int *index, int bytes) { bytes -= (len - pos); cur = xmlXPtrAdvanceNode(cur); cur = 0; + } else if (pos + bytes < len) { + pos += bytes; + *node = cur; + *index = pos; + return(0); } } return(-1); @@ -2366,7 +2372,7 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr string; xmlXPathObjectPtr position = NULL; xmlXPathObjectPtr number = NULL; - int found; + int found, pos, num; /* * Grab the arguments @@ -2377,10 +2383,14 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { if (nargs >= 4) { CHECK_TYPE(XPATH_NUMBER); number = valuePop(ctxt); + if (number != NULL) + num = number->floatval; } if (nargs >= 3) { CHECK_TYPE(XPATH_NUMBER); position = valuePop(ctxt); + if (position != NULL) + pos = position->floatval; } CHECK_TYPE(XPATH_STRING); string = valuePop(ctxt); @@ -2433,8 +2443,32 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { found = xmlXPtrSearchString(string->stringval, &start, &startindex, &fend, &fendindex); if (found == 1) { - xmlXPtrLocationSetAdd(newset, + if (position == NULL) { + xmlXPtrLocationSetAdd(newset, xmlXPtrNewRange(start, startindex, fend, fendindex)); + } else if (xmlXPtrAdvanceChar(&start, &startindex, + pos - 1) == 0) { + if ((number != NULL) && (num > 0)) { + int rindex; + xmlNodePtr rend; + rend = start; + rindex = startindex - 1; + if (xmlXPtrAdvanceChar(&rend, &rindex, + num) == 0) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + rend, rindex)); + } + } else if (num <= 0) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + start, startindex)); + } else { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + fend, fendindex)); + } + } start = fend; startindex = fendindex; if (string->stringval[0] == 0)