diff options
Diffstat (limited to 'xmlreader.c')
-rw-r--r-- | xmlreader.c | 143 |
1 files changed, 121 insertions, 22 deletions
diff --git a/xmlreader.c b/xmlreader.c index 254fd544..5649da9e 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -70,7 +70,8 @@ typedef enum { XML_TEXTREADER_ELEMENT= 1, XML_TEXTREADER_END= 2, XML_TEXTREADER_EMPTY= 3, - XML_TEXTREADER_BACKTRACK= 4 + XML_TEXTREADER_BACKTRACK= 4, + XML_TEXTREADER_DONE= 5 } xmlTextReaderState; struct _xmlTextReader { @@ -82,6 +83,8 @@ struct _xmlTextReader { xmlParserInputBufferPtr input; /* the input */ startElementSAXFunc startElement;/* initial SAX callbacks */ endElementSAXFunc endElement; /* idem */ + charactersSAXFunc characters; + cdataBlockSAXFunc cdataBlock; unsigned int base; /* base of the segment in the input */ unsigned int cur; /* current position in the input */ xmlNodePtr node; /* current node */ @@ -135,8 +138,13 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname, #ifdef DEBUG_CALLBACKS printf("xmlTextReaderStartElement(%s)\n", fullname); #endif - if ((reader != NULL) && (reader->startElement != NULL)) + if ((reader != NULL) && (reader->startElement != NULL)) { reader->startElement(ctx, fullname, atts); + if (ctxt->validate) { + ctxt->valid &= xmlValidatePushElement(&ctxt->vctxt, ctxt->myDoc, + ctxt->node, fullname); + } + } reader->state = XML_TEXTREADER_ELEMENT; } @@ -155,8 +163,16 @@ xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { #ifdef DEBUG_CALLBACKS printf("xmlTextReaderEndElement(%s)\n", fullname); #endif - if ((reader != NULL) && (reader->endElement != NULL)) + if ((reader != NULL) && (reader->endElement != NULL)) { + xmlNodePtr node = ctxt->node; + reader->endElement(ctx, fullname); + + if (ctxt->validate) { + ctxt->valid &= xmlValidatePopElement(&ctxt->vctxt, ctxt->myDoc, + node, fullname); + } + } if (reader->state == XML_TEXTREADER_ELEMENT) reader->state = XML_TEXTREADER_EMPTY; else @@ -164,6 +180,58 @@ xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { } /** + * xmlTextReaderCharacters: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * receiving some chars from the parser. + */ +static void +xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderCharacters()\n"); +#endif + if ((reader != NULL) && (reader->characters != NULL)) { + reader->characters(ctx, ch, len); + + if (ctxt->validate) { + ctxt->valid &= xmlValidatePushCData(&ctxt->vctxt, ch, len); + } + } +} + +/** + * xmlTextReaderCDataBlock: + * @ctx: the user data (XML parser context) + * @value: The pcdata content + * @len: the block length + * + * called when a pcdata block has been parsed + */ +static void +xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderCDataBlock()\n"); +#endif + if ((reader != NULL) && (reader->cdataBlock != NULL)) { + reader->cdataBlock(ctx, ch, len); + + if (ctxt->validate) { + ctxt->valid &= xmlValidatePushCData(&ctxt->vctxt, ch, len); + } + } +} + +/** * xmlTextReaderPushData: * @reader: the xmlTextReaderPtr used * @@ -177,10 +245,12 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { unsigned int cur = reader->cur; xmlBufferPtr inbuf; int val; + int oldstate; if ((reader->input == NULL) || (reader->input->buffer == NULL)) return(-1); + oldstate = reader->state; reader->state = XML_TEXTREADER_NONE; inbuf = reader->input->buffer; while (reader->state == XML_TEXTREADER_NONE) { @@ -192,6 +262,7 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { val = xmlParserInputBufferRead(reader->input, 4096); if (val <= 0) { reader->mode = XML_TEXTREADER_MODE_EOF; + reader->state = oldstate; return(val); } } else @@ -241,10 +312,14 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { * At the end of the stream signal that the work is done to the Push * parser. */ - if ((reader->mode == XML_TEXTREADER_MODE_EOF) && (cur >= inbuf->use)) { - val = xmlParseChunk(reader->ctxt, - (const char *) &inbuf->content[reader->cur], 0, 1); + if (reader->mode == XML_TEXTREADER_MODE_EOF) { + if (reader->mode != XML_TEXTREADER_DONE) { + val = xmlParseChunk(reader->ctxt, + (const char *) &inbuf->content[reader->cur], 0, 1); + reader->mode = XML_TEXTREADER_DONE; + } } + reader->state = oldstate; return(0); } @@ -303,19 +378,20 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { * that the parser didn't finished or that we arent at the end * of stream, continue processing. */ + while (((oldstate == XML_TEXTREADER_BACKTRACK) || + (reader->node->children == NULL) || + (reader->node->type == XML_ENTITY_REF_NODE) || + (reader->node->type == XML_DTD_NODE)) && + (reader->node->next == NULL) && + (reader->ctxt->nodeNr == olddepth) && + (reader->ctxt->instate != XML_PARSER_EOF)) { + val = xmlTextReaderPushData(reader); + if (val < 0) + return(-1); + if (reader->node == NULL) + return(0); + } if (oldstate != XML_TEXTREADER_BACKTRACK) { - while (((reader->node->children == NULL) || - (reader->node->type == XML_ENTITY_REF_NODE) || - (reader->node->type == XML_DTD_NODE)) && - (reader->node->next == NULL) && - (reader->ctxt->nodeNr == olddepth) && - (reader->ctxt->instate != XML_PARSER_EOF)) { - val = xmlTextReaderPushData(reader); - if (val < 0) - return(-1); - if (reader->node == NULL) - return(0); - } if ((reader->node->children != NULL) && (reader->node->type != XML_ENTITY_REF_NODE) && (reader->node->type != XML_DTD_NODE)) { @@ -348,6 +424,12 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { return(1); } + if ((oldstate == XML_TEXTREADER_ELEMENT) && + (reader->node->type == XML_ELEMENT_NODE)) { + reader->state = XML_TEXTREADER_END; + DUMP_READER + return(1); + } reader->node = reader->node->parent; if ((reader->node == NULL) || (reader->node->type == XML_DOCUMENT_NODE) || @@ -355,6 +437,10 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { (reader->node->type == XML_DOCB_DOCUMENT_NODE) || #endif (reader->node->type == XML_HTML_DOCUMENT_NODE)) { + if (reader->mode != XML_TEXTREADER_DONE) { + val = xmlParseChunk(reader->ctxt, "", 0, 1); + reader->mode = XML_TEXTREADER_DONE; + } reader->node = NULL; reader->depth = 0; @@ -501,13 +587,14 @@ xmlTextReaderReadBinHex(xmlTextReaderPtr reader, unsigned char *array, /** * xmlNewTextReader: * @input: the xmlParserInputBufferPtr used to read data + * @URI: the URI information for the source if available * * Create an xmlTextReader structure fed with @input * * Returns the new xmlTextReaderPtr or NULL in case of error */ xmlTextReaderPtr -xmlNewTextReader(xmlParserInputBufferPtr input) { +xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { xmlTextReaderPtr ret; int val; @@ -533,6 +620,10 @@ xmlNewTextReader(xmlParserInputBufferPtr input) { ret->sax->startElement = xmlTextReaderStartElement; ret->endElement = ret->sax->endElement; ret->sax->endElement = xmlTextReaderEndElement; + ret->characters = ret->sax->characters; + ret->sax->characters = xmlTextReaderCharacters; + ret->cdataBlock = ret->sax->cdataBlock; + ret->sax->cdataBlock = xmlTextReaderCDataBlock; ret->mode = XML_TEXTREADER_MODE_INITIAL; ret->node = NULL; @@ -540,15 +631,16 @@ xmlNewTextReader(xmlParserInputBufferPtr input) { val = xmlParserInputBufferRead(input, 4); if (val >= 4) { ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, - (const char *) ret->input->buffer->content, 4, NULL); + (const char *) ret->input->buffer->content, 4, URI); ret->base = 0; ret->cur = 4; } else { - ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, NULL); + ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); ret->base = 0; ret->cur = 0; } ret->ctxt->_private = ret; + ret->ctxt->linenumbers = 1; ret->allocs = XML_TEXTREADER_CTXT; return(ret); @@ -566,16 +658,23 @@ xmlTextReaderPtr xmlNewTextReaderFilename(const char *URI) { xmlParserInputBufferPtr input; xmlTextReaderPtr ret; + char *directory = NULL; input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); if (input == NULL) return(NULL); - ret = xmlNewTextReader(input); + ret = xmlNewTextReader(input, URI); if (ret == NULL) { xmlFreeParserInputBuffer(input); return(NULL); } ret->allocs |= XML_TEXTREADER_INPUT; + if (ret->ctxt->directory == NULL) + directory = xmlParserGetDirectory(URI); + if ((ret->ctxt->directory == NULL) && (directory != NULL)) + ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); + if (directory != NULL) + xmlFree(directory); return(ret); } |