diff options
Diffstat (limited to 'xml/apr_xml_libxml2.c')
-rw-r--r-- | xml/apr_xml_libxml2.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/xml/apr_xml_libxml2.c b/xml/apr_xml_libxml2.c new file mode 100644 index 000000000..a765f2359 --- /dev/null +++ b/xml/apr_xml_libxml2.c @@ -0,0 +1,96 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_xml.h" + +#include <libxml/parser.h> +#include <libxml/xmlerror.h> + +typedef xmlParserCtxtPtr XML_Parser; +typedef xmlParserErrors XML_Error; + +#include "apr_xml_internal.h" + +static apr_status_t cleanup_parser(void *ctx) +{ + apr_xml_parser *parser = ctx; + + xmlFreeParserCtxt(parser->xp); + parser->xp = NULL; + + return APR_SUCCESS; +} +static int libxml2_parse(apr_xml_parser* parser, const char* data, + apr_size_t sz, int final) +{ + parser->xp_err = xmlParseChunk(parser->xp, data, sz, final); + if (parser->xp_err != 0) { + xmlErrorPtr errptr = xmlCtxtGetLastError(parser->xp); + parser->xp_msg = errptr->message; + /* this misnomer is used as a test for (any) parser error. */ + parser->error = APR_XML_ERROR_EXPAT; + } + return parser->xp_err; +} +static XMLParserImpl xml_parser_libxml2 = { + libxml2_parse, + cleanup_parser +}; + +static const char APR_KW_DAV[] = { 0x44, 0x41, 0x56, 0x3A, '\0' }; + +XMLParserImpl* apr_xml_get_parser_impl(void) +{ + return &xml_parser_libxml2; +} + + +APR_DECLARE(apr_xml_parser *) apr_xml_parser_create_ex(apr_pool_t *pool, + void *start_func, void *end_func, void *cdata_func) +{ + apr_xml_parser *parser = apr_pcalloc(pool, sizeof(*parser)); + /* FIXME: This is a mismatch. We should create a single global + * sax instance and re-use it for every parser. That means we + * need an up-front initialisation function. + */ + xmlSAXHandlerPtr sax = apr_pcalloc(pool, sizeof(xmlSAXHandler)); + sax->startElement = start_func; + sax->endElement = end_func; + sax->characters = cdata_func; + sax->initialized = 1; + + parser->impl = apr_xml_get_parser_impl(); + + parser->p = pool; + parser->doc = apr_pcalloc(pool, sizeof(*parser->doc)); + + parser->doc->namespaces = apr_array_make(pool, 5, sizeof(const char *)); + + /* ### is there a way to avoid hard-coding this? */ + apr_xml_insert_uri(parser->doc->namespaces, APR_KW_DAV); + + parser->xp = xmlCreatePushParserCtxt(sax, parser, NULL, 0, NULL); + if (parser->xp == NULL) { + (*apr_pool_abort_get(pool))(APR_ENOMEM); + return NULL; + } + + apr_pool_cleanup_register(pool, parser, cleanup_parser, + apr_pool_cleanup_null); + + return parser; +} |