📄 sax2.c.svn-base
字号:
/* * SAX2.c : Default SAX2 handler to build a tree. * * See Copyright for the status of this software. * * Daniel Veillard <daniel@veillard.com> */#define IN_LIBXML#include "libxml.h"#include <stdlib.h>#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/parser.h>#include <libxml/parserInternals.h>#include <libxml/valid.h>#include <libxml/entities.h>#include <libxml/xmlerror.h>#include <libxml/debugXML.h>#include <libxml/xmlIO.h>#include <libxml/SAX.h>#include <libxml/uri.h>#include <libxml/valid.h>#include <libxml/HTMLtree.h>#include <libxml/globals.h>/* #define DEBUG_SAX2 *//* #define DEBUG_SAX2_TREE *//** * TODO: * * macro to flag unimplemented blocks * XML_CATALOG_PREFER user env to select between system/public prefered * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk> *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with *> values "system" and "public". I have made the default be "system" to *> match yours. */#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);/** * xmlValidError: * @ctxt: an XML validation parser context * @error: the error number * @msg: the error message * @str1: extra data * @str2: extra data * * Handle a validation error */static voidxmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const char *str1, const char *str2){ xmlStructuredErrorFunc schannel = NULL; if ((ctxt != NULL) && (ctxt->disableSAX != 0) && (ctxt->instate == XML_PARSER_EOF)) return; ctxt->errNo = error; if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) schannel = ctxt->sax->serror; __xmlRaiseError(schannel, ctxt->vctxt.error, ctxt->vctxt.userData, ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR, NULL, 0, (const char *) str1, (const char *) str2, NULL, 0, 0, msg, (const char *) str1, (const char *) str2); ctxt->valid = 0;}/** * xmlSAX2GetPublicId: * @ctx: the user data (XML parser context) * * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN" * * Returns a xmlChar * */const xmlChar *xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED){ /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ return(NULL);}/** * xmlSAX2GetSystemId: * @ctx: the user data (XML parser context) * * Provides the system ID, basically URL or filename e.g. * http://www.sgmlsource.com/dtds/memo.dtd * * Returns a xmlChar * */const xmlChar *xmlSAX2GetSystemId(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return((const xmlChar *) ctxt->input->filename); }/** * xmlSAX2GetLineNumber: * @ctx: the user data (XML parser context) * * Provide the line number of the current parsing point. * * Returns an int */intxmlSAX2GetLineNumber(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return(ctxt->input->line);}/** * xmlSAX2GetColumnNumber: * @ctx: the user data (XML parser context) * * Provide the column number of the current parsing point. * * Returns an int */intxmlSAX2GetColumnNumber(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return(ctxt->input->col);}/** * xmlSAX2IsStandalone: * @ctx: the user data (XML parser context) * * Is this document tagged standalone ? * * Returns 1 if true */intxmlSAX2IsStandalone(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return(ctxt->myDoc->standalone == 1);}/** * xmlSAX2HasInternalSubset: * @ctx: the user data (XML parser context) * * Does this document has an internal subset * * Returns 1 if true */intxmlSAX2HasInternalSubset(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return(ctxt->myDoc->intSubset != NULL);}/** * xmlSAX2HasExternalSubset: * @ctx: the user data (XML parser context) * * Does this document has an external subset * * Returns 1 if true */intxmlSAX2HasExternalSubset(void *ctx){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; return(ctxt->myDoc->extSubset != NULL);}/** * xmlSAX2InternalSubset: * @ctx: the user data (XML parser context) * @name: the root element name * @ExternalID: the external ID * @SystemID: the SYSTEM ID (e.g. filename or URL) * * Callback on internal subset declaration. */voidxmlSAX2InternalSubset(void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlDtdPtr dtd;#ifdef DEBUG_SAX xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n", name, ExternalID, SystemID);#endif if (ctxt->myDoc == NULL) return; dtd = xmlGetIntSubset(ctxt->myDoc); if (dtd != NULL) { if (ctxt->html) return; xmlUnlinkNode((xmlNodePtr) dtd); xmlFreeDtd(dtd); ctxt->myDoc->intSubset = NULL; } ctxt->myDoc->intSubset = xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);}/** * xmlSAX2ExternalSubset: * @ctx: the user data (XML parser context) * @name: the root element name * @ExternalID: the external ID * @SystemID: the SYSTEM ID (e.g. filename or URL) * * Callback on external subset declaration. */voidxmlSAX2ExternalSubset(void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;#ifdef DEBUG_SAX xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n", name, ExternalID, SystemID);#endif if (((ExternalID != NULL) || (SystemID != NULL)) && (((ctxt->validate) || (ctxt->loadsubset != 0)) && (ctxt->wellFormed && ctxt->myDoc))) { /* * Try to fetch and parse the external subset. */ xmlParserInputPtr oldinput; int oldinputNr; int oldinputMax; xmlParserInputPtr *oldinputTab; xmlParserInputPtr input = NULL; xmlCharEncoding enc; int oldcharset; /* * Ask the Entity resolver to load the damn thing */ if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID); if (input == NULL) { return; } xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID); /* * make sure we won't destroy the main document context */ oldinput = ctxt->input; oldinputNr = ctxt->inputNr; oldinputMax = ctxt->inputMax; oldinputTab = ctxt->inputTab; oldcharset = ctxt->charset; ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr)); if (ctxt->inputTab == NULL) { ctxt->errNo = XML_ERR_NO_MEMORY; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "xmlSAX2ExternalSubset: out of memory\n"); ctxt->errNo = XML_ERR_NO_MEMORY; ctxt->instate = XML_PARSER_EOF; ctxt->disableSAX = 1; ctxt->input = oldinput; ctxt->inputNr = oldinputNr; ctxt->inputMax = oldinputMax; ctxt->inputTab = oldinputTab; ctxt->charset = oldcharset; return; } ctxt->inputNr = 0; ctxt->inputMax = 5; ctxt->input = NULL; xmlPushInput(ctxt, input); /* * On the fly encoding conversion if needed */ if (ctxt->input->length >= 4) { enc = xmlDetectCharEncoding(ctxt->input->cur, 4); xmlSwitchEncoding(ctxt, enc); } if (input->filename == NULL) input->filename = (char *) xmlCanonicPath(SystemID); input->line = 1; input->col = 1; input->base = ctxt->input->cur; input->cur = ctxt->input->cur; input->free = NULL; /* * let's parse that entity knowing it's an external subset. */ xmlParseExternalSubset(ctxt, ExternalID, SystemID); /* * Free up the external entities */ while (ctxt->inputNr > 1) xmlPopInput(ctxt); xmlFreeInputStream(ctxt->input); xmlFree(ctxt->inputTab); /* * Restore the parsing context of the main entity */ ctxt->input = oldinput; ctxt->inputNr = oldinputNr; ctxt->inputMax = oldinputMax; ctxt->inputTab = oldinputTab; ctxt->charset = oldcharset; /* ctxt->wellFormed = oldwellFormed; */ }}/** * xmlSAX2ResolveEntity: * @ctx: the user data (XML parser context) * @publicId: The public ID of the entity * @systemId: The system ID of the entity * * The entity loader, to control the loading of external entities, * the application can either: * - override this xmlSAX2ResolveEntity() callback in the SAX block * - or better use the xmlSetExternalEntityLoader() function to * set up it's own entity resolution routine * * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. */xmlParserInputPtrxmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlParserInputPtr ret; xmlChar *URI; const char *base = NULL; if (ctxt->input != NULL) base = ctxt->input->filename; if (base == NULL) base = ctxt->directory; URI = xmlBuildURI(systemId, (const xmlChar *) base);#ifdef DEBUG_SAX xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);#endif ret = xmlLoadExternalEntity((const char *) URI, (const char *) publicId, ctxt); if (URI != NULL) xmlFree(URI); return(ret);}/** * xmlSAX2GetEntity: * @ctx: the user data (XML parser context) * @name: The entity name * * Get an entity by name * * Returns the xmlEntityPtr if found. */xmlEntityPtrxmlSAX2GetEntity(void *ctx, const xmlChar *name){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlEntityPtr ret = NULL;#ifdef DEBUG_SAX xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2GetEntity(%s)\n", name);#endif if (ctxt->inSubset == 0) { ret = xmlGetPredefinedEntity(name); if (ret != NULL) return(ret); } if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) { if (ctxt->inSubset == 2) { ctxt->myDoc->standalone = 0; ret = xmlGetDocEntity(ctxt->myDoc, name); ctxt->myDoc->standalone = 1; } else { ret = xmlGetDocEntity(ctxt->myDoc, name); if (ret == NULL) { ctxt->myDoc->standalone = 0; ret = xmlGetDocEntity(ctxt->myDoc, name); if (ret != NULL) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "Entity(%s) document marked standalone but requires external subset\n", name); ctxt->valid = 0; ctxt->wellFormed = 0; } ctxt->myDoc->standalone = 1; } } } else { ret = xmlGetDocEntity(ctxt->myDoc, name); } if ((ret != NULL) && ((ctxt->validate) || (ctxt->replaceEntities)) && (ret->children == NULL) && (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { int val; /* * for validation purposes we really need to fetch and * parse the external entity */ xmlNodePtr children; val = xmlParseCtxtExternalEntity(ctxt, ret->URI, ret->ExternalID, &children); if (val == 0) { xmlAddChildList((xmlNodePtr) ret, children); } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "Failure to process entity %s\n", name); ctxt->wellFormed = 0; ctxt->valid = 0; ctxt->validate = 0; return(NULL); } ret->owner = 1; } return(ret);}/** * xmlSAX2GetParameterEntity: * @ctx: the user data (XML parser context) * @name: The entity name * * Get a parameter entity by name * * Returns the xmlEntityPtr if found.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -