📄 xmlreader.c
字号:
if ((cur->type != XML_TEXT_NODE) &&
(cur->type != XML_COMMENT_NODE))
DICT_FREE(cur->name);
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_TEXT_NODE)) &&
(reader != NULL) && (reader->ctxt != NULL) &&
(reader->ctxt->freeElemsNr < 100)) {
cur->next = reader->ctxt->freeElems;
reader->ctxt->freeElems = cur;
reader->ctxt->freeElemsNr++;
} else {
xmlFree(cur);
}
}
/**
* xmlTextReaderFreeIDTable:
* @table: An id table
*
* Deallocate the memory used by an ID hash table.
*/
static void
xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
}
/**
* xmlTextReaderFreeDoc:
* @reader: the xmlTextReaderPtr used
* @cur: pointer to the document
*
* Free up all the structures used by a document, tree included.
*/
static void
xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
xmlDtdPtr extSubset, intSubset;
if (cur == NULL) return;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
/*
* Do this before freeing the children list to avoid ID lookups
*/
if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
cur->ids = NULL;
if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
cur->refs = NULL;
extSubset = cur->extSubset;
intSubset = cur->intSubset;
if (intSubset == extSubset)
extSubset = NULL;
if (extSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) cur->extSubset);
cur->extSubset = NULL;
xmlFreeDtd(extSubset);
}
if (intSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) cur->intSubset);
cur->intSubset = NULL;
xmlFreeDtd(intSubset);
}
if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
if (cur->version != NULL) xmlFree((char *) cur->version);
if (cur->name != NULL) xmlFree((char *) cur->name);
if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
if (cur->URL != NULL) xmlFree((char *) cur->URL);
if (cur->dict != NULL) xmlDictFree(cur->dict);
xmlFree(cur);
}
/************************************************************************
* *
* The reader core parser *
* *
************************************************************************/
#ifdef DEBUG_READER
static void
xmlTextReaderDebug(xmlTextReaderPtr reader) {
if ((reader == NULL) || (reader->ctxt == NULL)) {
fprintf(stderr, "xmlTextReader NULL\n");
return;
}
fprintf(stderr, "xmlTextReader: state %d depth %d ",
reader->state, reader->depth);
if (reader->node == NULL) {
fprintf(stderr, "node = NULL\n");
} else {
fprintf(stderr, "node %s\n", reader->node->name);
}
fprintf(stderr, " input: base %d, cur %d, depth %d: ",
reader->base, reader->cur, reader->ctxt->nodeNr);
if (reader->input->buffer == NULL) {
fprintf(stderr, "buffer is NULL\n");
} else {
#ifdef LIBXML_DEBUG_ENABLED
xmlDebugDumpString(stderr,
&reader->input->buffer->content[reader->cur]);
#endif
fprintf(stderr, "\n");
}
}
#endif
/**
* xmlTextReaderEntPush:
* @reader: the xmlTextReaderPtr used
* @value: the entity reference node
*
* Pushes a new entity reference node on top of the entities stack
*
* Returns 0 in case of error, the index in the stack otherwise
*/
static int
xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
{
if (reader->entMax <= 0) {
reader->entMax = 10;
reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
sizeof(reader->entTab[0]));
if (reader->entTab == NULL) {
xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
return (0);
}
}
if (reader->entNr >= reader->entMax) {
reader->entMax *= 2;
reader->entTab =
(xmlNodePtr *) xmlRealloc(reader->entTab,
reader->entMax *
sizeof(reader->entTab[0]));
if (reader->entTab == NULL) {
xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
return (0);
}
}
reader->entTab[reader->entNr] = value;
reader->ent = value;
return (reader->entNr++);
}
/**
* xmlTextReaderEntPop:
* @reader: the xmlTextReaderPtr used
*
* Pops the top element entity from the entities stack
*
* Returns the entity just removed
*/
static xmlNodePtr
xmlTextReaderEntPop(xmlTextReaderPtr reader)
{
xmlNodePtr ret;
if (reader->entNr <= 0)
return (0);
reader->entNr--;
if (reader->entNr > 0)
reader->ent = reader->entTab[reader->entNr - 1];
else
reader->ent = NULL;
ret = reader->entTab[reader->entNr];
reader->entTab[reader->entNr] = 0;
return (ret);
}
/**
* xmlTextReaderStartElement:
* @ctx: the user data (XML parser context)
* @fullname: The element name, including namespace prefix
* @atts: An array of name/value attributes pairs, NULL terminated
*
* called when an opening tag has been processed.
*/
static void
xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
const xmlChar **atts) {
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlTextReaderPtr reader = ctxt->_private;
#ifdef DEBUG_CALLBACKS
printf("xmlTextReaderStartElement(%s)\n", fullname);
#endif
if ((reader != NULL) && (reader->startElement != NULL)) {
reader->startElement(ctx, fullname, atts);
if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
(ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
(ctxt->input->cur[1] == '>'))
ctxt->node->extra = NODE_IS_EMPTY;
}
if (reader != NULL)
reader->state = XML_TEXTREADER_ELEMENT;
}
/**
* xmlTextReaderEndElement:
* @ctx: the user data (XML parser context)
* @fullname: The element name, including namespace prefix
*
* called when an ending tag has been processed.
*/
static void
xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlTextReaderPtr reader = ctxt->_private;
#ifdef DEBUG_CALLBACKS
printf("xmlTextReaderEndElement(%s)\n", fullname);
#endif
if ((reader != NULL) && (reader->endElement != NULL)) {
reader->endElement(ctx, fullname);
}
}
/**
* xmlTextReaderStartElementNs:
* @ctx: the user data (XML parser context)
* @localname: the local name of the element
* @prefix: the element namespace prefix if available
* @URI: the element namespace name if available
* @nb_namespaces: number of namespace definitions on that node
* @namespaces: pointer to the array of prefix/URI pairs namespace definitions
* @nb_attributes: the number of attributes on that node
* nb_defaulted: the number of defaulted attributes.
* @attributes: pointer to the array of (localname/prefix/URI/value/end)
* attribute values.
*
* called when an opening tag has been processed.
*/
static void
xmlTextReaderStartElementNs(void *ctx,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI,
int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar **attributes)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlTextReaderPtr reader = ctxt->_private;
#ifdef DEBUG_CALLBACKS
printf("xmlTextReaderStartElementNs(%s)\n", localname);
#endif
if ((reader != NULL) && (reader->startElementNs != NULL)) {
reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
namespaces, nb_attributes, nb_defaulted,
attributes);
if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
(ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
(ctxt->input->cur[1] == '>'))
ctxt->node->extra = NODE_IS_EMPTY;
}
if (reader != NULL)
reader->state = XML_TEXTREADER_ELEMENT;
}
/**
* xmlTextReaderEndElementNs:
* @ctx: the user data (XML parser context)
* @localname: the local name of the element
* @prefix: the element namespace prefix if available
* @URI: the element namespace name if available
*
* called when an ending tag has been processed.
*/
static void
xmlTextReaderEndElementNs(void *ctx,
const xmlChar * localname,
const xmlChar * prefix,
const xmlChar * URI)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlTextReaderPtr reader = ctxt->_private;
#ifdef DEBUG_CALLBACKS
printf("xmlTextReaderEndElementNs(%s)\n", localname);
#endif
if ((reader != NULL) && (reader->endElementNs != NULL)) {
reader->endElementNs(ctx, localname, prefix, URI);
}
}
/**
* 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);
}
}
/**
* 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);
}
}
/**
* xmlTextReaderPushData:
* @reader: the xmlTextReaderPtr used
*
* Push data down the progressive parser until a significant callback
* got raised.
*
* Returns -1 in case of failure, 0 otherwise
*/
static int
xmlTextReaderPushData(xmlTextReaderPtr reader) {
xmlBufferPtr inbuf;
int val, s;
xmlTextReaderState 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) {
if (inbuf->use < reader->cur + CHUNK_SIZE) {
/*
* Refill the buffer unless we are at the end of the stream
*/
if (reader->mode != XML_TEXTREADER_MODE_EOF) {
val = xmlParserInputBufferRead(reader->input, 4096);
if ((val == 0) &&
(inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
if (inbuf->use == reader->cur) {
reader->mode = XML_TEXTREADER_MODE_EOF;
reader->state = oldstate;
}
} else if (val < 0) {
reader->mode = XML_TEXTREADER_MODE_EOF;
reader->state = oldstate;
if ((oldstate != XML_TEXTREADER_START) ||
(reader->ctxt->myDoc != NULL))
return(val);
} else if (val == 0) {
/* mark the end of the stream and process the remains */
reader->mode = XML_TEXTREADER_MODE_EOF;
break;
}
} else
break;
}
/*
* parse by block of CHUNK_SIZE bytes, various tests show that
* it's the best tradeoff at least on a 1.2GH Duron
*/
if (inbuf->use >= reader->cur + CHUNK_SIZE) {
val = xmlParseChunk(reader->ctxt,
(const char *) &inbuf->content[reader->cur],
CHUNK_SIZE, 0);
reader->cur += CHUNK_SIZE;
if ((val != 0) || (reader->ctxt->wellFormed == 0))
return(-1);
} else {
s = inbuf->use - reader->cur;
val = xmlParseChunk(reader->ctxt,
(const char *) &inbuf->content[reader->cur],
s, 0);
reader->cur += s;
if ((val != 0) || (reader->ctxt->wellFormed == 0))
return(-1);
break;
}
}
/*
* Discard the consumed input when needed and possible
*/
if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
if ((reader->cur >= 4096) &&
(inbuf->use - reader->cur <= CHUNK_SIZE)) {
val = xmlBufferShrink(inbuf, reader->cur);
if (val >= 0) {
reader->cur -= val;
}
}
}
}
/*
* At the end of the stream signal that the work is done to the Push
* parser.
*/
else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
if (reader->mode != XML_TEXTREADER_DONE) {
s = inbuf->use - reader->cur;
val = xmlParseChunk(reader->ctxt,
(const char *) &inbuf->content[reader->cur],
s, 1);
reader->cur = inbuf->use;
reader->mode = XML_TEXTREADER_DONE;
if ((val != 0) || (reader->ctxt->wellFormed == 0))
return(-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -