📄 xmlreader.c
字号:
}
reader->state = oldstate;
return(0);
}
#ifdef LIBXML_REGEXP_ENABLED
/**
* xmlTextReaderValidatePush:
* @reader: the xmlTextReaderPtr used
*
* Push the current node for validation
*/
static void
xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
xmlNodePtr node = reader->node;
#ifdef LIBXML_VALID_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
reader->ctxt->myDoc, node, node->name);
} else {
/* TODO use the BuildQName interface */
xmlChar *qname;
qname = xmlStrdup(node->ns->prefix);
qname = xmlStrcat(qname, BAD_CAST ":");
qname = xmlStrcat(qname, node->name);
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
reader->ctxt->myDoc, node, qname);
if (qname != NULL)
xmlFree(qname);
}
}
#endif /* LIBXML_VALID_ENABLED */
#ifdef LIBXML_SCHEMAS_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
(reader->rngValidCtxt != NULL)) {
int ret;
if (reader->rngFullNode != NULL) return;
ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
reader->ctxt->myDoc,
node);
if (ret == 0) {
/*
* this element requires a full tree
*/
node = xmlTextReaderExpand(reader);
if (node == NULL) {
printf("Expand failed !\n");
ret = -1;
} else {
ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
reader->ctxt->myDoc,
node);
reader->rngFullNode = node;
}
}
if (ret != 1)
reader->rngValidErrors++;
}
#endif
}
/**
* xmlTextReaderValidateCData:
* @reader: the xmlTextReaderPtr used
* @data: pointer to the CData
* @len: lenght of the CData block in bytes.
*
* Push some CData for validation
*/
static void
xmlTextReaderValidateCData(xmlTextReaderPtr reader,
const xmlChar *data, int len) {
#ifdef LIBXML_VALID_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
data, len);
}
#endif /* LIBXML_VALID_ENABLED */
#ifdef LIBXML_SCHEMAS_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
(reader->rngValidCtxt != NULL)) {
int ret;
if (reader->rngFullNode != NULL) return;
ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
if (ret != 1)
reader->rngValidErrors++;
}
#endif
}
/**
* xmlTextReaderValidatePop:
* @reader: the xmlTextReaderPtr used
*
* Pop the current node from validation
*/
static void
xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
xmlNodePtr node = reader->node;
#ifdef LIBXML_VALID_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
reader->ctxt->myDoc, node, node->name);
} else {
/* TODO use the BuildQName interface */
xmlChar *qname;
qname = xmlStrdup(node->ns->prefix);
qname = xmlStrcat(qname, BAD_CAST ":");
qname = xmlStrcat(qname, node->name);
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
reader->ctxt->myDoc, node, qname);
if (qname != NULL)
xmlFree(qname);
}
}
#endif /* LIBXML_VALID_ENABLED */
#ifdef LIBXML_SCHEMAS_ENABLED
if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
(reader->rngValidCtxt != NULL)) {
int ret;
if (reader->rngFullNode != NULL) {
if (node == reader->rngFullNode)
reader->rngFullNode = NULL;
return;
}
ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
reader->ctxt->myDoc,
node);
if (ret != 1)
reader->rngValidErrors++;
}
#endif
}
/**
* xmlTextReaderValidateEntity:
* @reader: the xmlTextReaderPtr used
*
* Handle the validation when an entity reference is encountered and
* entity substitution is not activated. As a result the parser interface
* must walk through the entity and do the validation calls
*/
static void
xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
xmlNodePtr oldnode = reader->node;
xmlNodePtr node = reader->node;
xmlParserCtxtPtr ctxt = reader->ctxt;
do {
if (node->type == XML_ENTITY_REF_NODE) {
/*
* Case where the underlying tree is not availble, lookup the entity
* and walk it.
*/
if ((node->children == NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->getEntity != NULL)) {
node->children = (xmlNodePtr)
ctxt->sax->getEntity(ctxt, node->name);
}
if ((node->children != NULL) &&
(node->children->type == XML_ENTITY_DECL) &&
(node->children->children != NULL)) {
xmlTextReaderEntPush(reader, node);
node = node->children->children;
continue;
} else {
/*
* The error has probably be raised already.
*/
if (node == oldnode)
break;
node = node->next;
}
#ifdef LIBXML_REGEXP_ENABLED
} else if (node->type == XML_ELEMENT_NODE) {
reader->node = node;
xmlTextReaderValidatePush(reader);
} else if ((node->type == XML_TEXT_NODE) ||
(node->type == XML_CDATA_SECTION_NODE)) {
xmlTextReaderValidateCData(reader, node->content,
xmlStrlen(node->content));
#endif
}
/*
* go to next node
*/
if (node->children != NULL) {
node = node->children;
continue;
} else if (node->type == XML_ELEMENT_NODE) {
xmlTextReaderValidatePop(reader);
}
if (node->next != NULL) {
node = node->next;
continue;
}
do {
node = node->parent;
if (node->type == XML_ELEMENT_NODE) {
xmlNodePtr tmp;
if (reader->entNr == 0) {
while ((tmp = node->last) != NULL) {
if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
xmlUnlinkNode(tmp);
xmlTextReaderFreeNode(reader, tmp);
} else
break;
}
}
reader->node = node;
xmlTextReaderValidatePop(reader);
}
if ((node->type == XML_ENTITY_DECL) &&
(reader->ent != NULL) && (reader->ent->children == node)) {
node = xmlTextReaderEntPop(reader);
}
if (node == oldnode)
break;
if (node->next != NULL) {
node = node->next;
break;
}
} while ((node != NULL) && (node != oldnode));
} while ((node != NULL) && (node != oldnode));
reader->node = oldnode;
}
#endif /* LIBXML_REGEXP_ENABLED */
/**
* xmlTextReaderGetSuccessor:
* @cur: the current node
*
* Get the successor of a node if available.
*
* Returns the successor node or NULL
*/
static xmlNodePtr
xmlTextReaderGetSuccessor(xmlNodePtr cur) {
if (cur == NULL) return(NULL) ; /* ERROR */
if (cur->next != NULL) return(cur->next) ;
do {
cur = cur->parent;
if (cur == NULL) return(NULL);
if (cur->next != NULL) return(cur->next);
} while (cur != NULL);
return(cur);
}
/**
* xmlTextReaderDoExpand:
* @reader: the xmlTextReaderPtr used
*
* Makes sure that the current node is fully read as well as all its
* descendant. It means the full DOM subtree must be available at the
* end of the call.
*
* Returns 1 if the node was expanded successfully, 0 if there is no more
* nodes to read, or -1 in case of error
*/
static int
xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
int val;
if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
return(-1);
do {
if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
if (xmlTextReaderGetSuccessor(reader->node) != NULL)
return(1);
if (reader->ctxt->nodeNr < reader->depth)
return(1);
if (reader->mode == XML_TEXTREADER_MODE_EOF)
return(1);
val = xmlTextReaderPushData(reader);
if (val < 0)
return(-1);
} while(reader->mode != XML_TEXTREADER_MODE_EOF);
return(1);
}
/**
* xmlTextReaderCollectSiblings:
* @node: the first child
*
* Traverse depth-first through all sibling nodes and their children
* nodes and concatenate their content. This is an auxiliary function
* to xmlTextReaderReadString.
*
* Returns a string containing the content, or NULL in case of error.
*/
static xmlChar *
xmlTextReaderCollectSiblings(xmlNodePtr node)
{
xmlBufferPtr buffer;
xmlChar *ret;
buffer = xmlBufferCreate();
if (buffer == NULL)
return NULL;
for ( ; node != NULL; node = node->next) {
switch (node->type) {
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
xmlBufferCat(buffer, node->content);
break;
case XML_ELEMENT_NODE:
xmlBufferCat(buffer, xmlTextReaderCollectSiblings(node->children));
default:
break;
}
}
ret = buffer->content;
buffer->content = NULL;
xmlBufferFree(buffer);
return(ret);
}
/**
* xmlTextReaderRead:
* @reader: the xmlTextReaderPtr used
*
* Moves the position of the current instance to the next node in
* the stream, exposing its properties.
*
* Returns 1 if the node was read successfully, 0 if there is no more
* nodes to read, or -1 in case of error
*/
int
xmlTextReaderRead(xmlTextReaderPtr reader) {
int val, olddepth = 0;
xmlTextReaderState oldstate = XML_TEXTREADER_START;
xmlNodePtr oldnode = NULL;
if (reader == NULL)
return(-1);
reader->curnode = NULL;
if (reader->doc != NULL)
return(xmlTextReaderReadTree(reader));
if (reader->ctxt == NULL)
return(-1);
if (reader->ctxt->wellFormed != 1)
return(-1);
#ifdef DEBUG_READER
fprintf(stderr, "\nREAD ");
DUMP_READER
#endif
if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
/*
* Initial state
*/
do {
val = xmlTextReaderPushData(reader);
if (val < 0)
return(-1);
} while ((reader->ctxt->node == NULL) &&
((reader->mode != XML_TEXTREADER_MODE_EOF) &&
(reader->mode != XML_TEXTREADER_DONE)));
if (reader->ctxt->node == NULL) {
if (reader->ctxt->myDoc != NULL) {
reader->node = reader->ctxt->myDoc->children;
}
if (reader->node == NULL)
return(-1);
reader->state = XML_TEXTREADER_ELEMENT;
} else {
if (reader->ctxt->myDoc != NULL) {
reader->node = reader->ctxt->myDoc->children;
}
if (reader->node == NULL)
reader->node = reader->ctxt->nodeTab[0];
reader->state = XML_TEXTREADER_ELEMENT;
}
reader->depth = 0;
reader->ctxt->parseMode = XML_PARSE_READER;
goto node_found;
}
oldstate = reader->state;
olddepth = reader->ctxt->nodeNr;
oldnode = reader->node;
get_next_node:
if (reader->node == NULL) {
if (reader->mode == XML_TEXTREADER_DONE)
return(0);
else
return(-1);
}
/*
* If we are not backtracking on ancestors or examined nodes,
* that the parser didn't finished or that we arent at the end
* of stream, continue processing.
*/
while ((reader->node != NULL) && (reader->node->next == NULL) &&
(reader->ctxt->nodeNr == olddepth) &&
((oldstate == XML_TEXTREADER_BACKTRACK) ||
(reader->node->children == NULL) ||
(reader->node->type == XML_ENTITY_REF_NODE) ||
((reader->node->children != NULL) &&
(reader->node->children->type == XML_TEXT_NODE) &&
(reader->node->children->next == NULL)) ||
(reader->node->type == XML_DTD_NODE) ||
(reader->node->type == XML_DOCUMENT_NODE) ||
(reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
((reader->ctxt->node == NULL) ||
(reader->ctxt->node == reader->node) ||
(reader->ctxt->node == reader->node->parent)) &&
(reader->ctxt->instate != XML_PARSER_EOF)) {
val = xmlTextReaderPushData(reader);
if (val < 0)
return(-1);
if (reader->node == NULL)
goto node_end;
}
if (oldstate != XML_TEXTREADER_BACKTRACK) {
if ((reader->node->children != NULL) &&
(reader->node->type != XML_ENTITY_REF_NODE) &&
(reader->node->type != XML_XINCLUDE_START) &&
(reader->node->type != XML_DTD_NODE)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -