summaryrefslogtreecommitdiff
path: root/xml/apr_xml_libxml2.c
diff options
context:
space:
mode:
Diffstat (limited to 'xml/apr_xml_libxml2.c')
-rw-r--r--xml/apr_xml_libxml2.c96
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;
+}