From 517752b9859719c25e3eff6f5397de9dcd3bfd69 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 5 Apr 1999 12:20:10 +0000 Subject: [PATCH] Completed/revamped the SAX support, removed old namespace suppport, Daniel --- ChangeLog | 10 + SAX.c | 527 +++++++++++++++++++++++++-- entities.h | 4 +- include/libxml/entities.h | 4 +- include/libxml/parser.h | 43 ++- include/libxml/parserInternals.h | 21 +- include/libxml/tree.h | 4 +- include/libxml/valid.h | 12 +- parser.c | 602 ++++++++++++++----------------- parser.h | 43 ++- parserInternals.h | 21 +- tree.c | 4 +- tree.h | 4 +- valid.c | 10 +- valid.h | 12 +- 15 files changed, 925 insertions(+), 396 deletions(-) diff --git a/ChangeLog b/ChangeLog index 19b8c692..de4e14b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Mon Apr 5 14:14:40 CEST 1999 Daniel Veillard + + * parser.[ch] tree.[ch] SAX.c, parserInternals.h valid.[ch]: + large revamping of the parser to use SAX callbacks + http://www.megginson.com/SAX/ (or at least a C like interface + a la Expat). It's now possible to set up your own callbacks + and the parser will not build a DOM tree. + * test/* result/*: updated the test suite, I finally removed + the old Namespace draft support (PI based). + Fri Apr 2 17:57:32 CEST 1999 Daniel Veillard * Makefile.am: added test result to EXTRA_DIST for make tests diff --git a/SAX.c b/SAX.c index b4a6cb16..7f9ea18a 100644 --- a/SAX.c +++ b/SAX.c @@ -10,6 +10,8 @@ #include #include "tree.h" #include "parser.h" +#include "parserInternals.h" +#include "valid.h" #include "entities.h" #include "xml-error.h" @@ -80,6 +82,65 @@ xmlSAXLocator xmlDefaultSAXLocator = { getPublicId, getSystemId, getLineNumber, getColumnNumber }; +/** + * isStandalone: + * @ctxt: An XML parser context + * + * Is this document tagged standalone ? + * + * Returns 1 if true + */ +int +isStandalone(xmlParserCtxtPtr ctxt) +{ + return(ctxt->myDoc->standalone == 1); +} + +/** + * hasInternalSubset: + * @ctxt: An XML parser context + * + * Does this document has an internal subset + * + * Returns 1 if true + */ +int +hasInternalSubset(xmlParserCtxtPtr ctxt) +{ + return(ctxt->myDoc->intSubset != NULL); +} + +/** + * hasExternalSubset: + * @ctxt: An XML parser context + * + * Does this document has an external subset + * + * Returns 1 if true + */ +int +hasExternalSubset(xmlParserCtxtPtr ctxt) +{ + return(ctxt->myDoc->extSubset != NULL); +} + +/** + * hasInternalSubset: + * @ctxt: An XML parser context + * + * Does this document has an internal subset + */ +void +internalSubset(xmlParserCtxtPtr ctxt, const CHAR *name, + const CHAR *ExternalID, const CHAR *SystemID) +{ +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n", + name, ExternalID, SystemID); +#endif + xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID); +} + /** * resolveEntity: * @ctxt: An XML parser context @@ -102,9 +163,106 @@ resolveEntity(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId) fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId); #endif + /* + * TODO : not 100% sure that the appropriate handling in that case. + */ return(NULL); } +/** + * getEntity: + * @ctxt: An XML parser context + * @name: The entity name + * + * Get an entity by name + * + * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. + */ +xmlEntityPtr +getEntity(xmlParserCtxtPtr ctxt, const CHAR *name) +{ + xmlEntityPtr ret; + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.getEntity(%s)\n", name); +#endif + + ret = xmlGetDocEntity(ctxt->myDoc, name); + return(ret); +} + + +/** + * entityDecl: + * @ctxt: An XML parser context + * @name: the entity name + * @type: the entity type + * @publicId: The public ID of the entity + * @systemId: The system ID of the entity + * @content: the entity value (without processing). + * + * An entity definition has been parsed + */ +void +entityDecl(xmlParserCtxtPtr ctxt, const CHAR *name, int type, + const CHAR *publicId, const CHAR *systemId, CHAR *content) +{ + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", + name, type, publicId, systemId, content); +#endif + xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content); +} + +/** + * attributeDecl: + * @ctxt: An XML parser context + * @name: the attribute name + * @type: the attribute type + * @publicId: The public ID of the attribute + * @systemId: The system ID of the attribute + * @content: the attribute value (without processing). + * + * An attribute definition has been parsed + */ +void +attributeDecl(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name, + int type, int def, const CHAR *defaultValue, + xmlEnumerationPtr tree) +{ + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", + elem, name, type, def, defaultValue); +#endif + xmlAddAttributeDecl(ctxt->myDoc->intSubset, elem, name, type, def, + defaultValue, tree); +} + +/** + * elementDecl: + * @ctxt: An XML parser context + * @name: the element name + * @type: the element type + * @publicId: The public ID of the element + * @systemId: The system ID of the element + * @content: the element value (without processing). + * + * An element definition has been parsed + */ +void +elementDecl(xmlParserCtxtPtr ctxt, const CHAR *name, int type, + xmlElementContentPtr content) +{ + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n", + name, type); +#endif + xmlAddElementDecl(ctxt->myDoc->intSubset, name, type, content); +} + /** * notationDecl: * @ctxt: An XML parser context @@ -122,6 +280,7 @@ notationDecl(xmlParserCtxtPtr ctxt, const CHAR *name, #ifdef DEBUG_SAX fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId); #endif + xmlAddNotationDecl(ctxt->myDoc->intSubset, name, publicId, systemId); } /** @@ -171,9 +330,19 @@ setDocumentLocator(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc) void startDocument(xmlParserCtxtPtr ctxt) { + xmlDocPtr doc; + #ifdef DEBUG_SAX fprintf(stderr, "SAX.startDocument()\n"); #endif + doc = ctxt->myDoc = xmlNewDoc(ctxt->version); + if (doc != NULL) { + if (ctxt->encoding != NULL) + doc->encoding = xmlStrdup(ctxt->encoding); + else + doc->encoding = NULL; + doc->standalone = ctxt->standalone; + } } /** @@ -190,20 +359,152 @@ endDocument(xmlParserCtxtPtr ctxt) #endif } +/** + * attribute: + * @ctxt: An XML parser context + * @name: The attribute name + * @value: The attribute value + * + * Handle an attribute that has been read by the parser. + * The default handling is to convert the attribute into an + * DOM subtree and past it in a new xmlAttr element added to + * the element. + */ +void +attribute(xmlParserCtxtPtr ctxt, const CHAR *fullname, const CHAR *value) +{ + xmlAttrPtr ret; + CHAR *name; + CHAR *ns; + +/**************** +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value); +#endif + ****************/ + /* + * Split the full name into a namespace prefix and the tag name + */ + name = xmlSplitQName(fullname, &ns); + + /* + * Check whether it's a namespace definition + */ + if ((ns == NULL) && + (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && + (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) { + /* a default namespace definition */ + xmlNewNs(ctxt->node, value, NULL); + if (name != NULL) + free(name); + return; + } + if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && + (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) { + /* a standard namespace definition */ + xmlNewNs(ctxt->node, value, name); + free(ns); + if (name != NULL) + free(name); + return; + } + + ret = xmlNewProp(ctxt->node, name, NULL); + if (ret != NULL) + ret->val = xmlStringGetNodeList(ctxt->myDoc, value); + if (name != NULL) + free(name); + if (ns != NULL) + free(ns); +} + /** * startElement: * @ctxt: An XML parser context * @name: The element name + * @atts: An array of name/value attributes pairs, NULL terminated * * called when an opening tag has been processed. * TODO We currently have a small pblm with the arguments ... */ void -startElement(xmlParserCtxtPtr ctxt, const CHAR *name) +startElement(xmlParserCtxtPtr ctxt, const CHAR *fullname, const CHAR **atts) { + xmlNodePtr ret; + xmlNodePtr parent = ctxt->node; + xmlNsPtr ns; + CHAR *name; + CHAR *prefix; + const CHAR *att; + const CHAR *value; + + int i; + #ifdef DEBUG_SAX - fprintf(stderr, "SAX.startElement(%s)\n", name); + fprintf(stderr, "SAX.startElement(%s)\n", fullname); #endif + /* + * Split the full name into a namespace prefix and the tag name + */ + name = xmlSplitQName(fullname, &prefix); + + + /* + * Note : the namespace resolution is deferred until the end of the + * attributes parsing, since local namespace can be defined as + * an attribute at this level. + */ + ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL); + if (ret == NULL) return; + if (ctxt->myDoc->root == NULL) + ctxt->myDoc->root = ret; + + /* + * We are parsing a new node. + */ + nodePush(ctxt, ret); + + /* + * Link the child element + */ + if (parent != NULL) + xmlAddChild(parent, ctxt->node); + + /* + * process all the attributes. + */ + if (atts != NULL) { + i = 0; + att = atts[i++]; + value = atts[i++]; + while ((att != NULL) && (value != NULL)) { + /* + * Handle one pair of attribute/value + */ + attribute(ctxt, att, value); + + /* + * Next ones + */ + att = atts[i++]; + value = atts[i++]; + } + } + + /* + * Search the namespace, note that since the attributes have been + * processed, the local namespaces are available. + */ + ns = xmlSearchNs(ctxt->myDoc, ret, prefix); + if ((ns == NULL) && (parent != NULL)) + ns = xmlSearchNs(ctxt->myDoc, parent, prefix); + xmlSetNs(ret, ns); + + if (prefix != NULL) + free(prefix); + if (name != NULL) + free(name); + } /** @@ -216,47 +517,65 @@ startElement(xmlParserCtxtPtr ctxt, const CHAR *name) void endElement(xmlParserCtxtPtr ctxt, const CHAR *name) { + xmlParserNodeInfo node_info; + xmlNodePtr cur = ctxt->node; + #ifdef DEBUG_SAX - fprintf(stderr, "SAX.endElement(%s)\n", name); + if (name == NULL) + fprintf(stderr, "SAX.endElement(NULL)\n"); + else + fprintf(stderr, "SAX.endElement(%s)\n", name); #endif + + /* Capture end position and add node */ + if (cur != NULL && ctxt->record_info) { + node_info.end_pos = ctxt->input->cur - ctxt->input->base; + node_info.end_line = ctxt->input->line; + node_info.node = cur; + xmlParserAddNodeInfo(ctxt, &node_info); + } + + /* + * end of parsing of this node. + */ + nodePop(ctxt); } /** - * attribute: + * reference: * @ctxt: An XML parser context - * @name: The attribute name - * @value: The attribute value + * @name: The entity name * - * called when an attribute has been read by the parser. - * The default handling is to convert the attribute into an - * DOM subtree and past it in a new xmlAttr element added to - * the element. + * called when an entity reference is detected. */ void -attribute(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value) +reference(xmlParserCtxtPtr ctxt, const CHAR *name) { + xmlNodePtr ret; + #ifdef DEBUG_SAX - fprintf(stderr, "SAX.attribute(%s, %s)\n", name, value); + fprintf(stderr, "SAX.reference(%s)\n", name); #endif + ret = xmlNewReference(ctxt->myDoc, name); + xmlAddChild(ctxt->node, ret); } /** * characters: * @ctxt: An XML parser context * @ch: a CHAR string - * @start: the first char in the string * @len: the number of CHAR * * receiving some chars from the parser. * Question: how much at a time ??? */ void -characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len) +characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int len) { xmlNodePtr lastChild; #ifdef DEBUG_SAX - fprintf(stderr, "SAX.characters(%.30s, %d, %d)\n", ch, start, len); + fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len); #endif /* * Handle the data if any. If there is no child @@ -266,12 +585,12 @@ characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len) lastChild = xmlGetLastChild(ctxt->node); if (lastChild == NULL) - xmlNodeAddContentLen(ctxt->node, &ch[start], len); + xmlNodeAddContentLen(ctxt->node, ch, len); else { if (xmlNodeIsText(lastChild)) - xmlTextConcat(lastChild, &ch[start], len); + xmlTextConcat(lastChild, ch, len); else { - lastChild = xmlNewTextLen(&ch[start], len); + lastChild = xmlNewTextLen(ch, len); xmlAddChild(ctxt->node, lastChild); } } @@ -281,17 +600,16 @@ characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len) * ignorableWhitespace: * @ctxt: An XML parser context * @ch: a CHAR string - * @start: the first char in the string * @len: the number of CHAR * * receiving some ignorable whitespaces from the parser. * Question: how much at a time ??? */ void -ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len) +ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int len) { #ifdef DEBUG_SAX - fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d, %d)\n", ch, start, len); + fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len); #endif } @@ -313,19 +631,173 @@ processingInstruction(xmlParserCtxtPtr ctxt, const CHAR *target, #endif } +/** + * globalNamespace: + * @ctxt: An XML parser context + * @href: the namespace associated URN + * @prefix: the namespace prefix + * + * An old global namespace has been parsed. + */ +void +globalNamespace(xmlParserCtxtPtr ctxt, const CHAR *href, const CHAR *prefix) +{ +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix); +#endif + xmlNewGlobalNs(ctxt->myDoc, href, prefix); +} + +/** + * setNamespace: + * @ctxt: An XML parser context + * @name: the namespace prefix + * + * Set the current element namespace. + */ +void +setNamespace(xmlParserCtxtPtr ctxt, const CHAR *name) +{ + xmlNsPtr ns; + xmlNodePtr parent; + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.setNamespace(%s)\n", name); +#endif + ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name); + if (ns == NULL) { /* ctxt->node may not have a parent yet ! */ + if (ctxt->nodeNr >= 2) { + parent = ctxt->nodeTab[ctxt->nodeNr - 2]; + if (parent != NULL) + ns = xmlSearchNs(ctxt->myDoc, parent, name); + } + } + xmlSetNs(ctxt->node, ns); +} + +/** + * getNamespace: + * @ctxt: An XML parser context + * + * Get the current element namespace. + */ +xmlNsPtr +getNamespace(xmlParserCtxtPtr ctxt) +{ + xmlNsPtr ret; + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.getNamespace()\n"); +#endif + ret = ctxt->node->ns; + return(ret); +} + +/** + * checkNamespace: + * @ctxt: An XML parser context + * @namespace: the namespace to check against + * + * Check that the current element namespace is the same as the + * one read upon parsing. + */ +int +checkNamespace(xmlParserCtxtPtr ctxt, CHAR *namespace) +{ + xmlNodePtr cur = ctxt->node; + +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace); +#endif + + /* + * Check that the Name in the ETag is the same as in the STag. + */ + if (namespace == NULL) { + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, + "End tags for %s don't hold the namespace %s\n", + cur->name, cur->ns->prefix); + ctxt->wellFormed = 0; + } + } else { + if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, + "End tags %s holds a prefix %s not used by the open tag\n", + cur->name, namespace); + ctxt->wellFormed = 0; + } else if (strcmp(namespace, cur->ns->prefix)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, + "Start and End tags for %s don't use the same namespaces: %s and %s\n", + cur->name, cur->ns->prefix, namespace); + ctxt->wellFormed = 0; + } else + return(1); + } + return(0); +} + +/** + * namespaceDecl: + * @ctxt: An XML parser context + * @href: the namespace associated URN + * @prefix: the namespace prefix + * + * A namespace has been parsed. + */ +void +namespaceDecl(xmlParserCtxtPtr ctxt, const CHAR *href, const CHAR *prefix) +{ +#ifdef DEBUG_SAX + if (prefix == NULL) + fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href); + else + fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix); +#endif + xmlNewNs(ctxt->node, href, prefix); +} + +/** + * comment: + * @ctxt: An XML parser context + * @value: the comment content + * + * A comment has been parsed. + */ +void +comment(xmlParserCtxtPtr ctxt, const CHAR *value) +{ +#ifdef DEBUG_SAX + fprintf(stderr, "SAX.comment(%s)\n", value); +#endif + xmlNewDocComment(ctxt->myDoc, value); +} + xmlSAXHandler xmlDefaultSAXHandler = { + internalSubset, + isStandalone, + hasInternalSubset, + hasExternalSubset, resolveEntity, + getEntity, + entityDecl, notationDecl, + attributeDecl, + elementDecl, unparsedEntityDecl, setDocumentLocator, startDocument, endDocument, startElement, endElement, - attribute, + reference, characters, ignorableWhitespace, processingInstruction, + comment, xmlParserWarning, xmlParserError, xmlParserError, @@ -339,7 +811,15 @@ xmlSAXHandler xmlDefaultSAXHandler = { void xmlDefaultSAXHandlerInit(void) { + xmlDefaultSAXHandler.internalSubset = internalSubset; + xmlDefaultSAXHandler.isStandalone = isStandalone; + xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset; + xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset; xmlDefaultSAXHandler.resolveEntity = resolveEntity; + xmlDefaultSAXHandler.getEntity = getEntity; + xmlDefaultSAXHandler.entityDecl = entityDecl; + xmlDefaultSAXHandler.attributeDecl = attributeDecl; + xmlDefaultSAXHandler.elementDecl = elementDecl; xmlDefaultSAXHandler.notationDecl = notationDecl; xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl; xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator; @@ -347,10 +827,11 @@ xmlDefaultSAXHandlerInit(void) xmlDefaultSAXHandler.endDocument = endDocument; xmlDefaultSAXHandler.startElement = startElement; xmlDefaultSAXHandler.endElement = endElement; - xmlDefaultSAXHandler.attribute = attribute; + xmlDefaultSAXHandler.reference = reference; xmlDefaultSAXHandler.characters = characters; xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace; xmlDefaultSAXHandler.processingInstruction = processingInstruction; + xmlDefaultSAXHandler.comment = comment; xmlDefaultSAXHandler.warning = xmlParserWarning; xmlDefaultSAXHandler.error = xmlParserError; xmlDefaultSAXHandler.fatalError = xmlParserError; diff --git a/entities.h b/entities.h index 99ce163c..89770547 100644 --- a/entities.h +++ b/entities.h @@ -9,7 +9,7 @@ #ifndef __XML_ENTITIES_H__ #define __XML_ENTITIES_H__ -#include "parser.h" +#include "tree.h" #ifdef __cplusplus extern "C" { @@ -56,6 +56,8 @@ typedef xmlEntitiesTable *xmlEntitiesTablePtr; * External functions : */ +#include "parser.h" + void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type, const CHAR *ExternalID, const CHAR *SystemID, CHAR *content); void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type, diff --git a/include/libxml/entities.h b/include/libxml/entities.h index 99ce163c..89770547 100644 --- a/include/libxml/entities.h +++ b/include/libxml/entities.h @@ -9,7 +9,7 @@ #ifndef __XML_ENTITIES_H__ #define __XML_ENTITIES_H__ -#include "parser.h" +#include "tree.h" #ifdef __cplusplus extern "C" { @@ -56,6 +56,8 @@ typedef xmlEntitiesTable *xmlEntitiesTablePtr; * External functions : */ +#include "parser.h" + void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type, const CHAR *ExternalID, const CHAR *SystemID, CHAR *content); void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type, diff --git a/include/libxml/parser.h b/include/libxml/parser.h index 3dc84453..3e433a26 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -51,8 +51,12 @@ typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr; typedef struct _xmlParserCtxt { struct xmlSAXHandler *sax; /* The SAX handler */ - xmlDocPtr doc; /* the document being built */ + void *userData; /* the document being built */ + xmlDocPtr myDoc; /* the document being built */ int wellFormed; /* is the document well formed */ + const CHAR *version; /* the XML version string */ + const CHAR *encoding; /* encoding, if any */ + int standalone; /* standalone document */ /* Input stream stack */ xmlParserInputPtr input; /* Current input stream */ @@ -89,10 +93,24 @@ typedef xmlSAXLocator *xmlSAXLocatorPtr; * a SAX Exception. */ +#include "entities.h" + typedef xmlParserInputPtr (*resolveEntitySAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId); +typedef void (*internalSubsetSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, + const CHAR *ExternalID, const CHAR *SystemID); +typedef xmlEntityPtr (*getEntitySAXFunc) (xmlParserCtxtPtr ctxt, + const CHAR *name); +typedef void (*entityDeclSAXFunc) (xmlParserCtxtPtr ctxt, + const CHAR *name, int type, const CHAR *publicId, + const CHAR *systemId, CHAR *content); typedef void (*notationDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *publicId, const CHAR *systemId); +typedef void (*attributeDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *elem, + const CHAR *name, int type, int def, + const CHAR *defaultValue, xmlEnumerationPtr tree); +typedef void (*elementDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, + int type, xmlElementContentPtr content); typedef void (*unparsedEntityDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *publicId, const CHAR *systemId, const CHAR *notationName); @@ -100,33 +118,48 @@ typedef void (*setDocumentLocatorSAXFunc) (xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc); typedef void (*startDocumentSAXFunc) (xmlParserCtxtPtr ctxt); typedef void (*endDocumentSAXFunc) (xmlParserCtxtPtr ctxt); -typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); +typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, + const CHAR **atts); typedef void (*endElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); typedef void (*attributeSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value); +typedef void (*referenceSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); typedef void (*charactersSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *ch, - int start, int len); + int len); typedef void (*ignorableWhitespaceSAXFunc) (xmlParserCtxtPtr ctxt, - const CHAR *ch, int start, int len); + const CHAR *ch, int len); typedef void (*processingInstructionSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *target, const CHAR *data); +typedef void (*commentSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *value); typedef void (*warningSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); typedef void (*errorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); typedef void (*fatalErrorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); +typedef int (*isStandaloneSAXFunc) (xmlParserCtxtPtr ctxt); +typedef int (*hasInternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt); +typedef int (*hasExternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt); typedef struct xmlSAXHandler { + internalSubsetSAXFunc internalSubset; + isStandaloneSAXFunc isStandalone; + hasInternalSubsetSAXFunc hasInternalSubset; + hasExternalSubsetSAXFunc hasExternalSubset; resolveEntitySAXFunc resolveEntity; + getEntitySAXFunc getEntity; + entityDeclSAXFunc entityDecl; notationDeclSAXFunc notationDecl; + attributeDeclSAXFunc attributeDecl; + elementDeclSAXFunc elementDecl; unparsedEntityDeclSAXFunc unparsedEntityDecl; setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; startElementSAXFunc startElement; endElementSAXFunc endElement; - attributeSAXFunc attribute; + referenceSAXFunc reference; charactersSAXFunc characters; ignorableWhitespaceSAXFunc ignorableWhitespace; processingInstructionSAXFunc processingInstruction; + commentSAXFunc comment; warningSAXFunc warning; errorSAXFunc error; fatalErrorSAXFunc fatalError; diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h index 28ef54d1..75e9e130 100644 --- a/include/libxml/parserInternals.h +++ b/include/libxml/parserInternals.h @@ -529,6 +529,8 @@ xmlFreeInputStream(xmlParserInputPtr input); * Namespaces. */ CHAR * +xmlSplitQName(const CHAR *name, CHAR **prefix); +CHAR * xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt); CHAR * xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix); @@ -558,7 +560,7 @@ void xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata); CHAR * xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict); -xmlNodePtr +void xmlParseComment(xmlParserCtxtPtr ctxt, int create); CHAR * xmlParsePITarget(xmlParserCtxtPtr ctxt); @@ -601,17 +603,17 @@ CHAR * xmlParsePEReference(xmlParserCtxtPtr ctxt); void xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt); -xmlAttrPtr -xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node); -xmlNodePtr +CHAR * +xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value); +void xmlParseStartTag(xmlParserCtxtPtr ctxt); void -xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr); +xmlParseEndTag(xmlParserCtxtPtr ctxt); void xmlParseCDSect(xmlParserCtxtPtr ctxt); void xmlParseContent(xmlParserCtxtPtr ctxt); -xmlNodePtr +void xmlParseElement(xmlParserCtxtPtr ctxt); CHAR * xmlParseVersionNum(xmlParserCtxtPtr ctxt); @@ -628,5 +630,12 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt); void xmlParseMisc(xmlParserCtxtPtr ctxt); +/* + * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP + */ +extern int nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value); +extern xmlNodePtr nodePop(xmlParserCtxtPtr ctxt); +extern int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value); +extern xmlParserInputPtr inputPop(xmlParserCtxtPtr ctxt); #endif /* __XML_PARSER_INTERNALS_H__ */ diff --git a/include/libxml/tree.h b/include/libxml/tree.h index 4443836b..3f00aa09 100644 --- a/include/libxml/tree.h +++ b/include/libxml/tree.h @@ -283,8 +283,8 @@ xmlNodePtr xmlNewDocText(xmlDocPtr doc, const CHAR *content); xmlNodePtr xmlNewText(const CHAR *content); xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len); xmlNodePtr xmlNewTextLen(const CHAR *content, int len); -xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content); -xmlNodePtr xmlNewComment(CHAR *content); +xmlNodePtr xmlNewDocComment(xmlDocPtr doc, const CHAR *content); +xmlNodePtr xmlNewComment(const CHAR *content); xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name); xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive); xmlNodePtr xmlCopyNodeList(xmlNodePtr node); diff --git a/include/libxml/valid.h b/include/libxml/valid.h index 14a72285..22c824ab 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -54,8 +54,8 @@ typedef struct xmlAttributeTable { typedef xmlAttributeTable *xmlAttributeTablePtr; /* Notation */ -xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name, - CHAR *PublicID, CHAR *SystemID); +xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, + const CHAR *PublicID, const CHAR *SystemID); xmlNotationTablePtr xmlCopyNotationTable(xmlNotationTablePtr table); void xmlFreeNotationTable(xmlNotationTablePtr table); void xmlDumpNotationTable(xmlNotationTablePtr table); @@ -66,7 +66,7 @@ xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content); void xmlFreeElementContent(xmlElementContentPtr cur); /* Element */ -xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, +xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, xmlElementContentPtr content); xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table); void xmlFreeElementTable(xmlElementTablePtr table); @@ -78,9 +78,9 @@ void xmlFreeEnumeration(xmlEnumerationPtr cur); xmlEnumerationPtr xmlCopyEnumeration(xmlEnumerationPtr cur); /* Attribute */ -xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem, - CHAR *name, int type, int def, - CHAR *defaultValue, xmlEnumerationPtr tree); +xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, + const CHAR *name, int type, int def, + const CHAR *defaultValue, xmlEnumerationPtr tree); xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table); void xmlFreeAttributeTable(xmlAttributeTablePtr table); void xmlDumpAttributeTable(xmlAttributeTablePtr table); diff --git a/parser.c b/parser.c index 512611e0..f1ea2fb9 100644 --- a/parser.c +++ b/parser.c @@ -43,7 +43,7 @@ */ #define PUSH_AND_POP(type, name) \ -int name##Push(xmlParserCtxtPtr ctxt, type value) { \ +extern int name##Push(xmlParserCtxtPtr ctxt, type value) { \ if (ctxt->name##Nr >= ctxt->name##Max) { \ ctxt->name##Max *= 2; \ ctxt->name##Tab = (void *) realloc(ctxt->name##Tab, \ @@ -57,7 +57,7 @@ int name##Push(xmlParserCtxtPtr ctxt, type value) { \ ctxt->name = value; \ return(ctxt->name##Nr++); \ } \ -type name##Pop(xmlParserCtxtPtr ctxt) { \ +extern type name##Pop(xmlParserCtxtPtr ctxt) { \ type ret; \ if (ctxt->name##Nr <= 0) return(0); \ ctxt->name##Nr--; \ @@ -496,6 +496,7 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const CHAR *str, int len) { if (!(IS_BLANK(str[i]))) return(0); if (CUR != '<') return(0); + if (ctxt->node == NULL) return(0); lastChild = xmlGetLastChild(ctxt->node); if (lastChild == NULL) { if (ctxt->node->content != NULL) return(0); @@ -540,15 +541,14 @@ handle_as_char: /* * Just handle the content as a set of chars. */ - if (ctxt->sax != NULL) - ctxt->sax->characters(ctxt, entity->content, 0, len); + if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) + ctxt->sax->characters(ctxt, entity->content, len); } /* * Forward definition for recusive behaviour. */ -xmlNodePtr xmlParseElement(xmlParserCtxtPtr ctxt); CHAR *xmlParsePEReference(xmlParserCtxtPtr ctxt); CHAR *xmlParseReference(xmlParserCtxtPtr ctxt); @@ -625,6 +625,61 @@ xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix) { return(ret); } +/** + * xmlSplitQName: + * @name: an XML parser context + * @prefix: a CHAR ** + * + * parse an XML qualified name string + * + * [NS 5] QName ::= (Prefix ':')? LocalPart + * + * [NS 6] Prefix ::= NCName + * + * [NS 7] LocalPart ::= NCName + * + * Returns the function returns the local part, and prefix is updated + * to get the Prefix if any. + */ + +CHAR * +xmlSplitQName(const CHAR *name, CHAR **prefix) { + CHAR *ret = NULL; + const CHAR *q; + const CHAR *cur = name; + + *prefix = NULL; + if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL); + q = cur++; + + while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || + (*cur == '.') || (*cur == '-') || + (*cur == '_') || + (IS_COMBINING(*cur)) || + (IS_EXTENDER(*cur))) + cur++; + + ret = xmlStrndup(q, cur - q); + + if (*cur == ':') { + cur++; + if (!IS_LETTER(*cur) && (*cur != '_')) return(ret); + *prefix = ret; + + q = cur++; + + while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || + (*cur == '.') || (*cur == '-') || + (*cur == '_') || + (IS_COMBINING(*cur)) || + (IS_EXTENDER(*cur))) + cur++; + + ret = xmlStrndup(q, cur - q); + } + + return(ret); +} /** * xmlNamespaceParseNSDef: * @ctxt: an XML parser context @@ -789,9 +844,10 @@ xmlParseNamespace(xmlParserCtxtPtr ctxt) { /* * Register the DTD. - */ if (href != NULL) - xmlNewGlobalNs(ctxt->doc, href, prefix); + if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL)) + ctxt->sax->globalNamespace(ctxt, href, prefix); + */ if (prefix != NULL) free(prefix); if (href != NULL) free(href); @@ -1228,10 +1284,13 @@ xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) { * Ok the segment [q CUR_PTR] is to be consumed as chars. */ if (ctxt->sax != NULL) { - if (areBlanks(ctxt, q, CUR_PTR - q)) - ctxt->sax->ignorableWhitespace(ctxt, q, 0, CUR_PTR - q); - else - ctxt->sax->characters(ctxt, q, 0, CUR_PTR - q); + if (areBlanks(ctxt, q, CUR_PTR - q)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt, q, CUR_PTR - q); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt, q, CUR_PTR - q); + } } } @@ -1342,15 +1401,9 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict) { * must not occur within comments. " * * [15] Comment ::= '' - * - * TODO: this should call a SAX function which will handle (or not) the - * creation of the comment ! - * - * Returns the comment node, or NULL */ -xmlNodePtr +void xmlParseComment(xmlParserCtxtPtr ctxt, int create) { - xmlNodePtr ret = NULL; const CHAR *q, *start; const CHAR *r; CHAR *val; @@ -1359,7 +1412,7 @@ xmlParseComment(xmlParserCtxtPtr ctxt, int create) { * Check that there is a comment right here. */ if ((CUR != '<') || (NXT(1) != '!') || - (NXT(2) != '-') || (NXT(3) != '-')) return(NULL); + (NXT(2) != '-') || (NXT(3) != '-')) return; SKIP(4); start = q = CUR_PTR; @@ -1385,11 +1438,11 @@ xmlParseComment(xmlParserCtxtPtr ctxt, int create) { NEXT; if (create) { val = xmlStrndup(start, q - start); - ret = xmlNewDocComment(ctxt->doc, val); + if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL)) + ctxt->sax->comment(ctxt, val); free(val); } } - return(ret); } /** @@ -1449,54 +1502,29 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { */ target = xmlParsePITarget(ctxt); if (target != NULL) { - /* - * Support for the old Processing Instruction related to namespace. - */ - if ((target[0] == 'n') && (target[1] == 'a') && - (target[2] == 'm') && (target[3] == 'e') && - (target[4] == 's') && (target[5] == 'p') && - (target[6] == 'a') && (target[7] == 'c') && - (target[8] == 'e')) { - xmlParseNamespace(ctxt); - } else if ((target[0] == 'x') && (target[1] == 'm') && - (target[2] == 'l') && (target[3] == ':') && - (target[4] == 'n') && (target[5] == 'a') && - (target[6] == 'm') && (target[7] == 'e') && - (target[8] == 's') && (target[9] == 'p') && - (target[10] == 'a') && (target[11] == 'c') && - (target[12] == 'e')) { - xmlParseNamespace(ctxt); + const CHAR *q = CUR_PTR; + + while (IS_CHAR(CUR) && + ((CUR != '?') || (NXT(1) != '>'))) + NEXT; + if (!IS_CHAR(CUR)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, + "xmlParsePI: PI %s never end ...\n", target); + ctxt->wellFormed = 0; } else { - const CHAR *q = CUR_PTR; + CHAR *data; - while (IS_CHAR(CUR) && - ((CUR != '?') || (NXT(1) != '>'))) - NEXT; - if (!IS_CHAR(CUR)) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, - "xmlParsePI: PI %s never end ...\n", target); - ctxt->wellFormed = 0; - } else { - CHAR *data; + data = xmlStrndup(q, CUR_PTR - q); + SKIP(2); - data = xmlStrndup(CUR_PTR, CUR_PTR - q); - SKIP(2); - - /* - * SAX: PI detected. - */ - if (ctxt->sax) - ctxt->sax->processingInstruction(ctxt, target, data); - /* - * Unknown PI, ignore it ! - */ - else - xmlParserWarning(ctxt, - "xmlParsePI : skipping unknown PI %s\n", - target); - free(data); - } + /* + * SAX: PI detected. + */ + if ((ctxt->sax) && + (ctxt->sax->processingInstruction != NULL)) + ctxt->sax->processingInstruction(ctxt, target, data); + free(data); } free(target); } else { @@ -1577,7 +1605,8 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) { if (CUR == '>') { NEXT; - xmlAddNotationDecl(ctxt->doc->intSubset, name, Pubid, Systemid); + if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL)) + ctxt->sax->notationDecl(ctxt, name, Pubid, Systemid); } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, @@ -1662,14 +1691,16 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { if ((CUR == '"') || (CUR == '\'')) value = xmlParseEntityValue(ctxt); if (value) { - xmlAddDocEntity(ctxt->doc, name, + if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL)) + ctxt->sax->entityDecl(ctxt, name, XML_INTERNAL_PARAMETER_ENTITY, NULL, NULL, value); } else { URI = xmlParseExternalID(ctxt, &literal, 1); if (URI) { - xmlAddDocEntity(ctxt->doc, name, + if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL)) + ctxt->sax->entityDecl(ctxt, name, XML_EXTERNAL_PARAMETER_ENTITY, literal, URI, NULL); } @@ -1677,7 +1708,8 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { } else { if ((CUR == '"') || (CUR == '\'')) { value = xmlParseEntityValue(ctxt); - xmlAddDocEntity(ctxt->doc, name, + if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL)) + ctxt->sax->entityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY, NULL, NULL, value); } else { @@ -1701,11 +1733,13 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { } SKIP_BLANKS; ndata = xmlParseName(ctxt); - xmlAddDocEntity(ctxt->doc, name, + if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL)) + ctxt->sax->entityDecl(ctxt, name, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, literal, URI, ndata); } else { - xmlAddDocEntity(ctxt->doc, name, + if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL)) + ctxt->sax->entityDecl(ctxt, name, XML_EXTERNAL_GENERAL_PARSED_ENTITY, literal, URI, NULL); } @@ -2087,7 +2121,8 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) { "xmlParseAttributeListDecl: detected internal error\n"); break; } - xmlAddAttributeDecl(ctxt->doc->intSubset, elemName, attrName, + if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL)) + ctxt->sax->attributeDecl(ctxt, elemName, attrName, type, def, defaultValue, tree); if (attrName != NULL) free(attrName); @@ -2511,7 +2546,8 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) { ctxt->wellFormed = 0; } else { NEXT; - xmlAddElementDecl(ctxt->doc->intSubset, name, ret, content); + if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL)) + ctxt->sax->elementDecl(ctxt, name, ret, content); } if (name != NULL) { free(name); @@ -2632,7 +2668,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { CHAR *ret = NULL; const CHAR *q; CHAR *name; - xmlEntityPtr ent; + xmlEntityPtr ent = NULL; xmlParserInputPtr input = NULL; q = CUR_PTR; @@ -2655,19 +2691,28 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { * then * the entity referenced must have been declared * - * TODO: to be double checked !!! + * TODO: to be double checked !!! This is wrong ! */ - ent = xmlGetDocEntity(ctxt->doc, name); - if ((ctxt->doc->standalone == 1) || - ((ctxt->doc->intSubset == NULL) && - (ctxt->doc->extSubset == NULL))) { - if (ent == NULL) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, - "Entity '%s' not defined\n", name); - ctxt->wellFormed = 0; + if (ctxt->sax != NULL) { + if (ctxt->sax->getEntity != NULL) + ent = ctxt->sax->getEntity(ctxt, name); + + if (((ctxt->sax->isStandalone != NULL) && + ctxt->sax->isStandalone(ctxt) == 1) || + (((ctxt->sax->hasInternalSubset == NULL) || + ctxt->sax->hasInternalSubset(ctxt) == 0) && + ((ctxt->sax->hasExternalSubset == NULL) || + ctxt->sax->hasExternalSubset(ctxt) == 0))) { + if (ent == NULL) { + if ((ctxt->sax != NULL) && + (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, + "Entity '%s' not defined\n", name); + ctxt->wellFormed = 0; + } } - } + } else + ctxt->wellFormed = 0; /* * Well Formedness Constraint : @@ -2703,7 +2748,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { * - get a new input stream * - or keep the reference inline */ - if (ctxt->sax) + if ((ctxt->sax) && (ctxt->sax->resolveEntity != NULL)) input = ctxt->sax->resolveEntity(ctxt, NULL, name); if (input != NULL) xmlPushInput(ctxt, input); @@ -2768,7 +2813,7 @@ CHAR * xmlParsePEReference(xmlParserCtxtPtr ctxt) { CHAR *ret = NULL; CHAR *name; - xmlEntityPtr entity; + xmlEntityPtr entity = NULL; xmlParserInputPtr input; if (CUR == '%') { @@ -2781,7 +2826,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) { } else { if (CUR == ';') { NEXT; - entity = xmlGetDtdEntity(ctxt->doc, name); + if ((ctxt->sax != NULL) && (ctxt->sax->getEntity != NULL)) + entity = ctxt->sax->getEntity(ctxt, name); + /* TODO !!!! Must check that it's of the proper type !!! */ if (entity == NULL) { if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) ctxt->sax->warning(ctxt, @@ -2818,7 +2865,6 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) { void xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { - xmlDtdPtr dtd; CHAR *name; CHAR *ExternalID = NULL; CHAR *URI = NULL; @@ -2848,7 +2894,8 @@ xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { URI = xmlParseExternalID(ctxt, &ExternalID, 1); SKIP_BLANKS; - dtd = xmlCreateIntSubset(ctxt->doc, name, ExternalID, URI); + if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL)) + ctxt->sax->internalSubset(ctxt, name, ExternalID, URI); /* * Is there any DTD definition ? @@ -2901,7 +2948,7 @@ xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { /** * xmlParseAttribute: * @ctxt: an XML parser context - * @node: the node carrying the attribute + * @value: a CHAR ** used to store the value of the attribute * * parse an attribute * @@ -2916,17 +2963,15 @@ xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { * Also the case QName == xmlns:??? is handled independently as a namespace * definition. * - * Returns the attribute just parsed of NULL in case of error. + * Returns the attribute name, and the value in *value. */ -xmlAttrPtr -xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node) { +CHAR * +xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value) { CHAR *name, *val; - CHAR *ns; - CHAR *value = NULL; - xmlAttrPtr ret; - name = xmlNamespaceParseQName(ctxt, &ns); + *value = NULL; + name = xmlParseName(ctxt); if (name == NULL) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, "error parsing attribute name\n"); @@ -2941,61 +2986,17 @@ xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node) { if (CUR == '=') { NEXT; SKIP_BLANKS; - value = xmlParseAttValue(ctxt); + val = xmlParseAttValue(ctxt); } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, "Specification mandate value for attribute %s\n", name); ctxt->wellFormed = 0; - } - - /* - * Check whether it's a namespace definition - */ - if ((ns == NULL) && - (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && - (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) { - /* a default namespace definition */ - xmlNewNs(node, value, NULL); - if (name != NULL) - free(name); - if (value != NULL) - free(value); - return(NULL); - } - if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && - (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) { - /* a standard namespace definition */ - xmlNewNs(node, value, name); - free(ns); - if (name != NULL) - free(name); - if (value != NULL) - free(value); return(NULL); } - /* - * Well formedness requires at most one declaration of an attribute - */ - if ((val = xmlGetProp(ctxt->node, name)) != NULL) { - free(val); - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, "Attribute %s redefined\n", name); - ctxt->wellFormed = 0; - ret = NULL; - } else { - ret = xmlNewProp(ctxt->node, name, NULL); - if (ret != NULL) - ret->val = xmlStringGetNodeList(ctxt->doc, value); - } - - if (ns != NULL) - free(ns); - if (value != NULL) - free(value); - free(name); - return(ret); + *value = val; + return(name); } /** @@ -3014,47 +3015,30 @@ xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node) { * [NS 8] STag ::= '<' QName (S Attribute)* S? '>' * * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>' - * - * Returns the XML new node or NULL. */ -xmlNodePtr +void xmlParseStartTag(xmlParserCtxtPtr ctxt) { - CHAR *namespace, *name; - xmlNsPtr ns = NULL; - xmlNodePtr ret = NULL; - xmlNodePtr parent = ctxt->node; + CHAR *name; + CHAR *attname; + CHAR *attvalue; + const CHAR **atts = NULL; + int nbatts = 0; + int maxatts = 0; + int i; - if (CUR != '<') return(NULL); + if (CUR != '<') return; NEXT; - name = xmlNamespaceParseQName(ctxt, &namespace); + name = xmlParseName(ctxt); if (name == NULL) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, "xmlParseStartTag: invalid element name\n"); ctxt->wellFormed = 0; - return(NULL); + return; } - /* - * Note : the namespace resolution is deferred until the end of the - * attributes parsing, since local namespace can be defined as - * an attribute at this level. - */ - ret = xmlNewDocNode(ctxt->doc, ns, name, NULL); - if (ret == NULL) { - if (namespace != NULL) - free(namespace); - free(name); - return(NULL); - } - - /* - * We are parsing a new node. - */ - nodePush(ctxt, ret); - /* * Now parse the attributes, it ends up with the ending * @@ -3066,9 +3050,50 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) { ((CUR != '/') || (NXT(1) != '>'))) { const CHAR *q = CUR_PTR; - xmlParseAttribute(ctxt, ret); - SKIP_BLANKS; + attname = xmlParseAttribute(ctxt, &attvalue); + if ((attname != NULL) && (attvalue != NULL)) { + /* + * Well formedness requires at most one declaration of an attribute + */ + for (i = 0; i < nbatts;i += 2) { + if (!xmlStrcmp(atts[i], attname)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt, "Attribute %s redefined\n", + name); + ctxt->wellFormed = 0; + free(attname); + free(attvalue); + break; + } + } + /* + * Add the pair to atts + */ + if (atts == NULL) { + maxatts = 10; + atts = (const CHAR **) malloc(maxatts * sizeof(CHAR *)); + if (atts == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", + maxatts * sizeof(CHAR *)); + return; + } + } else if (nbatts + 2 < maxatts) { + maxatts *= 2; + atts = (const CHAR **) realloc(atts, maxatts * sizeof(CHAR *)); + if (atts == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", + maxatts * sizeof(CHAR *)); + return; + } + } + atts[nbatts++] = attname; + atts[nbatts++] = attvalue; + atts[nbatts] = NULL; + atts[nbatts + 1] = NULL; + } + + SKIP_BLANKS; if (q == CUR_PTR) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, @@ -3078,39 +3103,22 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) { } } - /* - * Search the namespace - */ - ns = xmlSearchNs(ctxt->doc, ret, namespace); - if (ns == NULL) /* ret still doesn't have a parent yet ! */ - ns = xmlSearchNs(ctxt->doc, parent, namespace); - xmlSetNs(ret, ns); - if (namespace != NULL) - free(namespace); - /* * SAX: Start of Element ! */ - if (ctxt->sax != NULL) - ctxt->sax->startElement(ctxt, name); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt, name, atts); + free(name); - - /* - * Link the child element - */ - if (ctxt->nodeNr < 2) return(ret); - parent = ctxt->nodeTab[ctxt->nodeNr - 2]; - if (parent != NULL) - xmlAddChild(parent, ctxt->node); - - return(ret); + if (atts != NULL) { + for (i = 0;i < nbatts;i++) free((CHAR *) atts[i]); + free(atts); + } } /** * xmlParseEndTag: * @ctxt: an XML parser context - * @nsPtr: the current node namespace definition - * @tagPtr: CHAR** receive the tag value * * parse an end of tag * @@ -3118,18 +3126,12 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) { * * With namespace * - * [9] ETag ::= '' - * - * tagPtr receive the tag name just read + * [NS 9] ETag ::= '' */ void -xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr) { - CHAR *namespace, *name; - xmlNsPtr ns = NULL; - - *nsPtr = NULL; - *tagPtr = NULL; +xmlParseEndTag(xmlParserCtxtPtr ctxt) { + CHAR *name; if ((CUR != '<') || (NXT(1) != '/')) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) @@ -3139,17 +3141,7 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr) { } SKIP(2); - name = xmlNamespaceParseQName(ctxt, &namespace); - - /* - * Search the namespace - */ - ns = xmlSearchNs(ctxt->doc, ctxt->node, namespace); - if (namespace != NULL) - free(namespace); - - *nsPtr = ns; - *tagPtr = name; + name = xmlParseName(ctxt); /* * We should definitely be at the ending "S? '>'" part @@ -3162,6 +3154,15 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr) { } else NEXT; + /* + * SAX: End of Tag + */ + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt, name); + + if (name != NULL) + free(name); + return; } @@ -3221,10 +3222,14 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { * Ok the segment [base CUR_PTR] is to be consumed as chars. */ if (ctxt->sax != NULL) { - if (areBlanks(ctxt, base, CUR_PTR - base)) - ctxt->sax->ignorableWhitespace(ctxt, base, 0, (CUR_PTR - base) - 2); - else - ctxt->sax->characters(ctxt, base, 0, (CUR_PTR - base) - 2); + if (areBlanks(ctxt, base, CUR_PTR - base)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt, base, + (CUR_PTR - base) - 2); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt, base, (CUR_PTR - base) - 2); + } } } @@ -3239,11 +3244,8 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { void xmlParseContent(xmlParserCtxtPtr ctxt) { - xmlNodePtr ret = NULL; - while ((CUR != '<') || (NXT(1) != '/')) { const CHAR *test = CUR_PTR; - ret = NULL; /* * First case : a Processing Instruction. @@ -3251,6 +3253,7 @@ xmlParseContent(xmlParserCtxtPtr ctxt) { if ((CUR == '<') && (NXT(1) == '?')) { xmlParsePI(ctxt); } + /* * Second case : a CDSection */ @@ -3261,19 +3264,22 @@ xmlParseContent(xmlParserCtxtPtr ctxt) { (NXT(8) == '[')) { xmlParseCDSect(ctxt); } + /* * Third case : a comment */ else if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '-') && (NXT(3) == '-')) { - ret = xmlParseComment(ctxt, 1); + xmlParseComment(ctxt, 1); } + /* * Fourth case : a sub-element. */ else if (CUR == '<') { - ret = xmlParseElement(ctxt); + xmlParseElement(ctxt); } + /* * Fifth case : a reference. If if has not been resolved, * parsing returns it's Name, create the node @@ -3285,19 +3291,19 @@ xmlParseContent(xmlParserCtxtPtr ctxt) { /* * inline predefined entity. */ - if (ctxt->sax != NULL) - ctxt->sax->characters(ctxt, val, 0, xmlStrlen(val)); + if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) + ctxt->sax->characters(ctxt, val, xmlStrlen(val)); } else { /* * user defined entity, create a node. */ - ret = xmlNewReference(ctxt->doc, val); - xmlAddChild(ctxt->node, ret); - ret = NULL; + if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL)) + ctxt->sax->reference(ctxt, val); } free(val); } } + /* * Last case, text. Note that References are handled directly. */ @@ -3330,42 +3336,27 @@ xmlParseContent(xmlParserCtxtPtr ctxt) { * [39] element ::= EmptyElemTag | STag content ETag * * [41] Attribute ::= Name Eq AttValue - * - * Returns the XML new node or NULL */ - -xmlNodePtr +void xmlParseElement(xmlParserCtxtPtr ctxt) { - xmlNodePtr ret; const CHAR *openTag = CUR_PTR; xmlParserNodeInfo node_info; - CHAR *endTag; - xmlNsPtr endNs; /* Capture start position */ node_info.begin_pos = CUR_PTR - ctxt->input->base; node_info.begin_line = ctxt->input->line; - ret = xmlParseStartTag(ctxt); - if (ret == NULL) { - return(NULL); - } + xmlParseStartTag(ctxt); /* * Check for an Empty Element. */ if ((CUR == '/') && (NXT(1) == '>')) { SKIP(2); - if (ctxt->sax != NULL) - ctxt->sax->endElement(ctxt, ret->name); - - /* - * end of parsing of this node. - */ - nodePop(ctxt); - - return(ret); + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt, NULL); + return; } if (CUR == '>') NEXT; else { @@ -3376,10 +3367,11 @@ xmlParseElement(xmlParserCtxtPtr ctxt) { /* * end of parsing of this node. + * TODO !!!!!!!! check the macro in case of non DOM parsing */ nodePop(ctxt); - return(NULL); + return; } /* @@ -3394,61 +3386,17 @@ xmlParseElement(xmlParserCtxtPtr ctxt) { /* * end of parsing of this node. + * TODO !!!!!!!! check the macro in case of non DOM parsing */ nodePop(ctxt); - return(NULL); + return; } /* * parse the end of tag: 'ns) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, - "Start and End tags don't use the same namespace\n%.30s\n%.30s\n", - openTag, endTag); - ctxt->wellFormed = 0; - } - if (endTag == NULL ) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, "The End tag has no name\n%.30s\n", openTag); - ctxt->wellFormed = 0; - } else if (xmlStrcmp(ret->name, endTag)) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt, - "Start and End tags don't use the same name\n%.30s\n%.30s\n", - openTag, endTag); - ctxt->wellFormed = 0; - } - /* - * SAX: End of Tag - */ - else if (ctxt->sax != NULL) - ctxt->sax->endElement(ctxt, endTag); - - if (endTag != NULL) - free(endTag); - - /* Capture end position and add node */ - if ( ret != NULL && ctxt->record_info ) { - node_info.end_pos = CUR_PTR - ctxt->input->base; - node_info.end_line = ctxt->input->line; - node_info.node = ret; - xmlParserAddNodeInfo(ctxt, &node_info); - } - - /* - * end of parsing of this node. - */ - nodePop(ctxt); - - return(ret); + xmlParseEndTag(ctxt); } /** @@ -3746,7 +3694,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { version = xmlParseVersionInfo(ctxt); if (version == NULL) version = xmlCharStrdup(XML_DEFAULT_VERSION); - ctxt->doc = xmlNewDoc(version); + ctxt->version = xmlStrdup(version); free(version); /* @@ -3761,12 +3709,12 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { ctxt->sax->error(ctxt, "Blank needed here\n"); ctxt->wellFormed = 0; } - ctxt->doc->encoding = xmlParseEncodingDecl(ctxt); + ctxt->encoding = xmlParseEncodingDecl(ctxt); /* * We may have the standalone status. */ - if ((ctxt->doc->encoding != NULL) && (!IS_BLANK(CUR))) { + if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) { if ((CUR == '?') && (NXT(1) == '>')) { SKIP(2); return; @@ -3776,7 +3724,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { ctxt->wellFormed = 0; } SKIP_BLANKS; - ctxt->doc->standalone = xmlParseSDDecl(ctxt); + ctxt->standalone = xmlParseSDDecl(ctxt); SKIP_BLANKS; if ((CUR == '?') && (NXT(1) == '>')) { @@ -3842,10 +3790,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { /* * SAX: beginning of the document processing. */ - if (ctxt->sax) + if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) ctxt->sax->setDocumentLocator(ctxt, &xmlDefaultSAXLocator); - if (ctxt->sax) - ctxt->sax->startDocument(ctxt); /* * We should check for encoding here and plug-in some @@ -3889,12 +3835,10 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { /* SKIP_EOL(cur); */ SKIP_BLANKS; } else { - CHAR *version; - - version = xmlCharStrdup(XML_DEFAULT_VERSION); - ctxt->doc = xmlNewDoc(version); - free(version); + ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); } + if ((ctxt->sax) && (ctxt->sax->startDocument)) + ctxt->sax->startDocument(ctxt); /* * The Misc part of the Prolog @@ -3917,7 +3861,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { /* * Time to start parsing the tree itself */ - ctxt->doc->root = xmlParseElement(ctxt); + xmlParseElement(ctxt); /* * The Misc part at the end @@ -3934,7 +3878,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { /* * SAX: end of the document processing. */ - if (ctxt->sax) + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt); if (! ctxt->wellFormed) return(-1); return(0); @@ -4004,11 +3948,11 @@ xmlSAXParseDoc(xmlSAXHandlerPtr sax, CHAR *cur, int recovery) { if (sax != NULL) ctxt->sax = sax; xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || recovery) ret = ctxt->doc; + if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; else { ret = NULL; - xmlFreeDoc(ctxt->doc); - ctxt->doc = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; } xmlFreeParserCtxt(ctxt); @@ -4187,11 +4131,11 @@ xmlDocPtr xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename, xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || recovery) ret = ctxt->doc; + if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; else { ret = NULL; - xmlFreeDoc(ctxt->doc); - ctxt->doc = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; } xmlFreeParserCtxt(ctxt); @@ -4300,11 +4244,11 @@ xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) { xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || recovery) ret = ctxt->doc; + if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; else { ret = NULL; - xmlFreeDoc(ctxt->doc); - ctxt->doc = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; } xmlFreeParserCtxt(ctxt); @@ -4355,6 +4299,9 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt) ctxt->inputNr = 0; ctxt->inputMax = 5; ctxt->input = NULL; + ctxt->version = NULL; + ctxt->encoding = NULL; + ctxt->standalone = -1; /* Allocate the Node stack */ ctxt->nodeTab = (xmlNodePtr *) malloc(10 * sizeof(xmlNodePtr)); @@ -4363,7 +4310,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt) ctxt->node = NULL; ctxt->sax = &xmlDefaultSAXHandler; - ctxt->doc = NULL; + ctxt->myDoc = NULL; ctxt->wellFormed = 1; ctxt->record_info = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); @@ -4374,7 +4321,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt) * @ctxt: an XML parser context * * Free all the memory used by a parser context. However the parsed - * document in ctxt->doc is not freed. + * document in ctxt->myDoc is not freed. */ void @@ -4390,6 +4337,7 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt) if (ctxt->nodeTab != NULL) free(ctxt->nodeTab); if (ctxt->inputTab != NULL) free(ctxt->inputTab); + if (ctxt->version != NULL) free(ctxt->version); free(ctxt); } diff --git a/parser.h b/parser.h index 3dc84453..3e433a26 100644 --- a/parser.h +++ b/parser.h @@ -51,8 +51,12 @@ typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr; typedef struct _xmlParserCtxt { struct xmlSAXHandler *sax; /* The SAX handler */ - xmlDocPtr doc; /* the document being built */ + void *userData; /* the document being built */ + xmlDocPtr myDoc; /* the document being built */ int wellFormed; /* is the document well formed */ + const CHAR *version; /* the XML version string */ + const CHAR *encoding; /* encoding, if any */ + int standalone; /* standalone document */ /* Input stream stack */ xmlParserInputPtr input; /* Current input stream */ @@ -89,10 +93,24 @@ typedef xmlSAXLocator *xmlSAXLocatorPtr; * a SAX Exception. */ +#include "entities.h" + typedef xmlParserInputPtr (*resolveEntitySAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId); +typedef void (*internalSubsetSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, + const CHAR *ExternalID, const CHAR *SystemID); +typedef xmlEntityPtr (*getEntitySAXFunc) (xmlParserCtxtPtr ctxt, + const CHAR *name); +typedef void (*entityDeclSAXFunc) (xmlParserCtxtPtr ctxt, + const CHAR *name, int type, const CHAR *publicId, + const CHAR *systemId, CHAR *content); typedef void (*notationDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *publicId, const CHAR *systemId); +typedef void (*attributeDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *elem, + const CHAR *name, int type, int def, + const CHAR *defaultValue, xmlEnumerationPtr tree); +typedef void (*elementDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, + int type, xmlElementContentPtr content); typedef void (*unparsedEntityDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *publicId, const CHAR *systemId, const CHAR *notationName); @@ -100,33 +118,48 @@ typedef void (*setDocumentLocatorSAXFunc) (xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc); typedef void (*startDocumentSAXFunc) (xmlParserCtxtPtr ctxt); typedef void (*endDocumentSAXFunc) (xmlParserCtxtPtr ctxt); -typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); +typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, + const CHAR **atts); typedef void (*endElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); typedef void (*attributeSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value); +typedef void (*referenceSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name); typedef void (*charactersSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *ch, - int start, int len); + int len); typedef void (*ignorableWhitespaceSAXFunc) (xmlParserCtxtPtr ctxt, - const CHAR *ch, int start, int len); + const CHAR *ch, int len); typedef void (*processingInstructionSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *target, const CHAR *data); +typedef void (*commentSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *value); typedef void (*warningSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); typedef void (*errorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); typedef void (*fatalErrorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...); +typedef int (*isStandaloneSAXFunc) (xmlParserCtxtPtr ctxt); +typedef int (*hasInternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt); +typedef int (*hasExternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt); typedef struct xmlSAXHandler { + internalSubsetSAXFunc internalSubset; + isStandaloneSAXFunc isStandalone; + hasInternalSubsetSAXFunc hasInternalSubset; + hasExternalSubsetSAXFunc hasExternalSubset; resolveEntitySAXFunc resolveEntity; + getEntitySAXFunc getEntity; + entityDeclSAXFunc entityDecl; notationDeclSAXFunc notationDecl; + attributeDeclSAXFunc attributeDecl; + elementDeclSAXFunc elementDecl; unparsedEntityDeclSAXFunc unparsedEntityDecl; setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; startElementSAXFunc startElement; endElementSAXFunc endElement; - attributeSAXFunc attribute; + referenceSAXFunc reference; charactersSAXFunc characters; ignorableWhitespaceSAXFunc ignorableWhitespace; processingInstructionSAXFunc processingInstruction; + commentSAXFunc comment; warningSAXFunc warning; errorSAXFunc error; fatalErrorSAXFunc fatalError; diff --git a/parserInternals.h b/parserInternals.h index 28ef54d1..75e9e130 100644 --- a/parserInternals.h +++ b/parserInternals.h @@ -529,6 +529,8 @@ xmlFreeInputStream(xmlParserInputPtr input); * Namespaces. */ CHAR * +xmlSplitQName(const CHAR *name, CHAR **prefix); +CHAR * xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt); CHAR * xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix); @@ -558,7 +560,7 @@ void xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata); CHAR * xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict); -xmlNodePtr +void xmlParseComment(xmlParserCtxtPtr ctxt, int create); CHAR * xmlParsePITarget(xmlParserCtxtPtr ctxt); @@ -601,17 +603,17 @@ CHAR * xmlParsePEReference(xmlParserCtxtPtr ctxt); void xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt); -xmlAttrPtr -xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node); -xmlNodePtr +CHAR * +xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value); +void xmlParseStartTag(xmlParserCtxtPtr ctxt); void -xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr); +xmlParseEndTag(xmlParserCtxtPtr ctxt); void xmlParseCDSect(xmlParserCtxtPtr ctxt); void xmlParseContent(xmlParserCtxtPtr ctxt); -xmlNodePtr +void xmlParseElement(xmlParserCtxtPtr ctxt); CHAR * xmlParseVersionNum(xmlParserCtxtPtr ctxt); @@ -628,5 +630,12 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt); void xmlParseMisc(xmlParserCtxtPtr ctxt); +/* + * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP + */ +extern int nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value); +extern xmlNodePtr nodePop(xmlParserCtxtPtr ctxt); +extern int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value); +extern xmlParserInputPtr inputPop(xmlParserCtxtPtr ctxt); #endif /* __XML_PARSER_INTERNALS_H__ */ diff --git a/tree.c b/tree.c index a331fe1d..13c30875 100644 --- a/tree.c +++ b/tree.c @@ -1088,7 +1088,7 @@ xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) { * Returns a pointer to the new node object. */ xmlNodePtr -xmlNewComment(CHAR *content) { +xmlNewComment(const CHAR *content) { xmlNodePtr cur; /* @@ -1128,7 +1128,7 @@ xmlNewComment(CHAR *content) { * Returns a pointer to the new node object. */ xmlNodePtr -xmlNewDocComment(xmlDocPtr doc, CHAR *content) { +xmlNewDocComment(xmlDocPtr doc, const CHAR *content) { xmlNodePtr cur; cur = xmlNewComment(content); diff --git a/tree.h b/tree.h index 4443836b..3f00aa09 100644 --- a/tree.h +++ b/tree.h @@ -283,8 +283,8 @@ xmlNodePtr xmlNewDocText(xmlDocPtr doc, const CHAR *content); xmlNodePtr xmlNewText(const CHAR *content); xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len); xmlNodePtr xmlNewTextLen(const CHAR *content, int len); -xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content); -xmlNodePtr xmlNewComment(CHAR *content); +xmlNodePtr xmlNewDocComment(xmlDocPtr doc, const CHAR *content); +xmlNodePtr xmlNewComment(const CHAR *content); xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name); xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive); xmlNodePtr xmlCopyNodeList(xmlNodePtr node); diff --git a/valid.c b/valid.c index 3cb6276c..2c1be9f2 100644 --- a/valid.c +++ b/valid.c @@ -216,7 +216,7 @@ xmlCreateElementTable(void) { * Returns NULL if not, othervise the entity */ xmlElementPtr -xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, +xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, xmlElementContentPtr content) { xmlElementPtr ret, cur; xmlElementTablePtr table; @@ -560,8 +560,9 @@ xmlCreateAttributeTable(void) { * Returns NULL if not, othervise the entity */ xmlAttributePtr -xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem, CHAR *name, int type, int def, - CHAR *defaultValue, xmlEnumerationPtr tree) { +xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name, + int type, int def, const CHAR *defaultValue, + xmlEnumerationPtr tree) { xmlAttributePtr ret, cur; xmlAttributeTablePtr table; int i; @@ -890,7 +891,8 @@ xmlCreateNotationTable(void) { * Returns NULL if not, othervise the entity */ xmlNotationPtr -xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name, CHAR *PublicID, CHAR *SystemID) { +xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID, + const CHAR *SystemID) { xmlNotationPtr ret, cur; xmlNotationTablePtr table; int i; diff --git a/valid.h b/valid.h index 14a72285..22c824ab 100644 --- a/valid.h +++ b/valid.h @@ -54,8 +54,8 @@ typedef struct xmlAttributeTable { typedef xmlAttributeTable *xmlAttributeTablePtr; /* Notation */ -xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name, - CHAR *PublicID, CHAR *SystemID); +xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, + const CHAR *PublicID, const CHAR *SystemID); xmlNotationTablePtr xmlCopyNotationTable(xmlNotationTablePtr table); void xmlFreeNotationTable(xmlNotationTablePtr table); void xmlDumpNotationTable(xmlNotationTablePtr table); @@ -66,7 +66,7 @@ xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content); void xmlFreeElementContent(xmlElementContentPtr cur); /* Element */ -xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, +xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, xmlElementContentPtr content); xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table); void xmlFreeElementTable(xmlElementTablePtr table); @@ -78,9 +78,9 @@ void xmlFreeEnumeration(xmlEnumerationPtr cur); xmlEnumerationPtr xmlCopyEnumeration(xmlEnumerationPtr cur); /* Attribute */ -xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem, - CHAR *name, int type, int def, - CHAR *defaultValue, xmlEnumerationPtr tree); +xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, + const CHAR *name, int type, int def, + const CHAR *defaultValue, xmlEnumerationPtr tree); xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table); void xmlFreeAttributeTable(xmlAttributeTablePtr table); void xmlDumpAttributeTable(xmlAttributeTablePtr table);