1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-21 14:53:44 +03:00

parser: Implement xmlCtxtParseDtd and xmlCtxtValidateDtd

This allows to use the context's error handler, options and other
settings.

Fixes #808.
This commit is contained in:
Nick Wellnhofer
2024-11-15 16:30:52 +01:00
parent 764b8086d1
commit 7f8c436c75
3 changed files with 100 additions and 95 deletions

View File

@@ -1183,6 +1183,15 @@ XMLPUBFUN xmlDocPtr
#endif /* LIBXML_SAX1_ENABLED */ #endif /* LIBXML_SAX1_ENABLED */
#ifdef LIBXML_VALID_ENABLED #ifdef LIBXML_VALID_ENABLED
XMLPUBFUN xmlDtdPtr
xmlCtxtParseDtd (xmlParserCtxtPtr ctxt,
xmlParserInputPtr input,
const xmlChar *ExternalID,
const xmlChar *SystemID);
XMLPUBFUN int
xmlCtxtValidateDtd (xmlParserCtxtPtr ctxt,
xmlDocPtr doc,
xmlDtdPtr dtd);
XML_DEPRECATED XML_DEPRECATED
XMLPUBFUN xmlDtdPtr XMLPUBFUN xmlDtdPtr
xmlSAXParseDTD (xmlSAXHandlerPtr sax, xmlSAXParseDTD (xmlSAXHandlerPtr sax,

167
parser.c
View File

@@ -11719,12 +11719,81 @@ xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
* * * *
************************************************************************/ ************************************************************************/
/**
* xmlCtxtParseDtd:
* @ctxt: a parser context
* @input: a parser input
* @publicId: public ID of the DTD (optional)
* @systemId: system ID of the DTD (optional)
*
* Parse a DTD.
*
* Option XML_PARSE_DTDLOAD should be enabled in the parser context
* to make external entities work.
*
* Availabe since 2.14.0.
*
* Returns the resulting xmlDtdPtr or NULL in case of error.
* @input will be freed by the function in any case.
*/
xmlDtdPtr
xmlCtxtParseDtd(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
const xmlChar *publicId, const xmlChar *systemId) {
xmlDtdPtr ret;
if (xmlPushInput(ctxt, input) < 0) {
xmlFreeInputStream(input);
return(NULL);
}
if (publicId == NULL)
publicId = BAD_CAST "none";
if (systemId == NULL)
systemId = BAD_CAST "none";
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
if (ctxt->myDoc == NULL) {
xmlErrMemory(ctxt);
return(NULL);
}
ctxt->myDoc->properties = XML_DOC_INTERNAL;
ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
publicId, systemId);
xmlDetectEncoding(ctxt);
xmlParseExternalSubset(ctxt, publicId, systemId);
if (ctxt->wellFormed) {
ret = ctxt->myDoc->extSubset;
ctxt->myDoc->extSubset = NULL;
if (ret != NULL) {
xmlNodePtr tmp;
ret->doc = NULL;
tmp = ret->children;
while (tmp != NULL) {
tmp->doc = NULL;
tmp = tmp->next;
}
}
} else {
ret = NULL;
}
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
return(ret);
}
/** /**
* xmlIOParseDTD: * xmlIOParseDTD:
* @sax: the SAX handler block or NULL * @sax: the SAX handler block or NULL
* @input: an Input Buffer * @input: an Input Buffer
* @enc: the charset encoding if known * @enc: the charset encoding if known
* *
* DEPRECATED: Use xmlCtxtParseDtd.
*
* Load and parse a DTD * Load and parse a DTD
* *
* Returns the resulting xmlDtdPtr or NULL in case of error. * Returns the resulting xmlDtdPtr or NULL in case of error.
@@ -11759,54 +11828,13 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
return(NULL); return(NULL);
} }
/*
* plug some encoding conversion routines here.
*/
if (xmlPushInput(ctxt, pinput) < 0) {
xmlFreeInputStream(pinput);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
if (enc != XML_CHAR_ENCODING_NONE) { if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc); xmlSwitchEncoding(ctxt, enc);
} }
/* ret = xmlCtxtParseDtd(ctxt, pinput, NULL, NULL);
* let's parse that entity knowing it's an external subset.
*/
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
if (ctxt->myDoc == NULL) {
xmlErrMemory(ctxt);
return(NULL);
}
ctxt->myDoc->properties = XML_DOC_INTERNAL;
ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
BAD_CAST "none", BAD_CAST "none");
xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
if (ctxt->myDoc != NULL) {
if (ctxt->wellFormed) {
ret = ctxt->myDoc->extSubset;
ctxt->myDoc->extSubset = NULL;
if (ret != NULL) {
xmlNodePtr tmp;
ret->doc = NULL;
tmp = ret->children;
while (tmp != NULL) {
tmp->doc = NULL;
tmp = tmp->next;
}
}
} else {
ret = NULL;
}
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
xmlFreeParserCtxt(ctxt); xmlFreeParserCtxt(ctxt);
return(ret); return(ret);
} }
@@ -11816,7 +11844,7 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
* @ExternalID: a NAME* containing the External ID of the DTD * @ExternalID: a NAME* containing the External ID of the DTD
* @SystemID: a NAME* containing the URL to the DTD * @SystemID: a NAME* containing the URL to the DTD
* *
* DEPRECATED: Don't use. * DEPRECATED: Use xmlCtxtParseDtd.
* *
* Load and parse an external subset. * Load and parse an external subset.
* *
@@ -11862,65 +11890,14 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
return(NULL); return(NULL);
} }
/*
* plug some encoding conversion routines here.
*/
if (xmlPushInput(ctxt, input) < 0) {
xmlFreeInputStream(input);
xmlFreeParserCtxt(ctxt);
if (systemIdCanonic != NULL)
xmlFree(systemIdCanonic);
return(NULL);
}
xmlDetectEncoding(ctxt);
if (input->filename == NULL) if (input->filename == NULL)
input->filename = (char *) systemIdCanonic; input->filename = (char *) systemIdCanonic;
else else
xmlFree(systemIdCanonic); xmlFree(systemIdCanonic);
/* ret = xmlCtxtParseDtd(ctxt, input, ExternalID, SystemID);
* let's parse that entity knowing it's an external subset.
*/
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
if (ctxt->myDoc == NULL) {
xmlErrMemory(ctxt);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
ctxt->myDoc->properties = XML_DOC_INTERNAL;
ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
ExternalID, SystemID);
if (ctxt->myDoc->extSubset == NULL) {
xmlFreeDoc(ctxt->myDoc);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
xmlParseExternalSubset(ctxt, ExternalID, SystemID);
if (ctxt->myDoc != NULL) {
if (ctxt->wellFormed) {
ret = ctxt->myDoc->extSubset;
ctxt->myDoc->extSubset = NULL;
if (ret != NULL) {
xmlNodePtr tmp;
ret->doc = NULL;
tmp = ret->children;
while (tmp != NULL) {
tmp->doc = NULL;
tmp = tmp->next;
}
}
} else {
ret = NULL;
}
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
xmlFreeParserCtxt(ctxt); xmlFreeParserCtxt(ctxt);
return(ret); return(ret);
} }

19
valid.c
View File

@@ -6479,6 +6479,25 @@ xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
return(ret); return(ret);
} }
/**
* xmlCtxtValidateDtd:
* @ctxt: a parser context
* @doc: a document instance
* @dtd: a dtd instance
*
* Validate a document against a DTD.
*
* Like xmlValidateDtd but uses the parser context's error handler.
*
* Availabe since 2.14.0.
*
* Returns 1 if valid or 0 otherwise.
*/
int
xmlCtxtValidateDtd(xmlParserCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
return(xmlValidateDtd(&ctxt->vctxt, doc, dtd));
}
static void static void
xmlValidateNotationCallback(void *payload, void *data, xmlValidateNotationCallback(void *payload, void *data,
const xmlChar *name ATTRIBUTE_UNUSED) { const xmlChar *name ATTRIBUTE_UNUSED) {