LibreOffice Module shell (master) 1
xml_parser.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <xml_parser.hxx>
23
24#ifdef _WIN32
25#include <utilities.hxx>
26#else
27#define UTF8ToWString(s) s
28#endif
29
30#include <assert.h>
31
32namespace /* private */
33{
34
35 /* Extracts the local part of tag without
36 namespace decoration e.g. meta:creator -> creator */
37 const XML_Char COLON = ':';
38
39 const XML_Char* get_local_name(const XML_Char* rawname)
40 {
41 const XML_Char* p = rawname;
42
43 // go to the end
44 while (*p) p++;
45
46 // go back until the first ':'
47 while (*p != COLON && p > rawname)
48 p--;
49
50 // if we are on a colon one step forward
51 if (*p == COLON)
52 p++;
53
54 return p;
55 }
56
57 xml_parser* get_parser_instance(void* data)
58 {
59 return static_cast<xml_parser*>(XML_GetUserData(
60 static_cast<XML_Parser>(data)));
61 }
62
63 bool has_only_whitespaces(const XML_Char* s, int len)
64 {
65 const XML_Char* p = s;
66 for (int i = 0; i < len; i++)
67 if (*p++ != ' ') return false;
68 return true;
69 }
70}
71
73 document_handler_(nullptr),
74 xml_parser_(XML_ParserCreate(nullptr))
75{
76 init();
77}
78
80{
81 XML_ParserFree(xml_parser_);
82}
83
84/* Callback functions will be called by the parser on
85 different events */
86
87extern "C"
88{
89
90static void xml_start_element_handler(void* UserData, const XML_Char* name, const XML_Char** atts)
91{
92 assert(UserData != nullptr);
93
94 xml_parser* pImpl = get_parser_instance(UserData);
95
97 if (!pDocHdl)
98 return;
99
101
102 int i = 0;
103
104 while(atts[i])
105 {
106 attributes[UTF8ToWString(reinterpret_cast<const char*>(get_local_name(atts[i])))] = UTF8ToWString(reinterpret_cast<const char*>(atts[i+1]));
107 i += 2; // skip to next pair
108 }
109
110 pDocHdl->start_element(
111 UTF8ToWString(reinterpret_cast<const char*>(name)), UTF8ToWString(reinterpret_cast<const char*>(get_local_name(name))), attributes);
112}
113
114static void xml_end_element_handler(void* UserData, const XML_Char* name)
115{
116 assert(UserData);
117
118 xml_parser* pImpl = get_parser_instance(UserData);
120 if (pDocHdl)
121 pDocHdl->end_element(UTF8ToWString(reinterpret_cast<const char*>(name)), UTF8ToWString(reinterpret_cast<const char*>(get_local_name(name))));
122}
123
124static void xml_character_data_handler(void* UserData, const XML_Char* s, int len)
125{
126 assert(UserData);
127
128 xml_parser* pImpl = get_parser_instance(UserData);
130 if (pDocHdl)
131 {
132 if (has_only_whitespaces(s,len))
133 pDocHdl->ignore_whitespace(UTF8ToWString(std::string(reinterpret_cast<const char*>(s), len)));
134 else
135 pDocHdl->characters(UTF8ToWString(std::string(reinterpret_cast<const char*>(s), len)));
136 }
137}
138
139static void xml_comment_handler(void* UserData, const XML_Char* Data)
140{
141 assert(UserData);
142
143 xml_parser* pImpl = get_parser_instance(UserData);
145 if (pDocHdl)
146 pDocHdl->comment(UTF8ToWString(reinterpret_cast<const char*>(Data)));
147}
148
149} // extern "C"
150
152{
153 XML_SetUserData(xml_parser_, this);
154
155 // we use the parser as handler argument,
156 // so we could use it if necessary, the
157 // UserData are usable anyway using
158 // XML_GetUserData(...)
159 XML_UseParserAsHandlerArg(xml_parser_);
160
161 XML_SetElementHandler(
165
166 XML_SetCharacterDataHandler(
169
170 XML_SetCommentHandler(
173}
174
175void xml_parser::parse(const char* XmlData, size_t Length, bool IsFinal)
176{
177 if (XML_STATUS_ERROR ==
178 XML_Parse(xml_parser_, XmlData, static_cast<int>(Length), IsFinal))
179 {
181 XML_ErrorString(XML_GetErrorCode(xml_parser_)));
182 }
183}
184
186 i_xml_parser_event_handler* event_handler)
187{
188 document_handler_ = event_handler;
189}
190
191
192/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void end_element(const string_t &raw_name, const string_t &local_name)=0
virtual void comment(const string_t &comment)=0
virtual void characters(const string_t &character)=0
virtual void start_element(const string_t &raw_name, const string_t &local_name, const xml_tag_attribute_container_t &attributes)=0
virtual void ignore_whitespace(const string_t &whitespaces)=0
i_xml_parser_event_handler * document_handler_
Definition: xml_parser.hxx:94
void init()
Definition: xml_parser.cxx:151
void set_document_handler(i_xml_parser_event_handler *event_handler)
Set a document handler.
Definition: xml_parser.cxx:185
i_xml_parser_event_handler * get_document_handler() const
Returns the currently used document handler or null if no document handler was set before.
Definition: xml_parser.hxx:88
void parse(const char *XmlData, size_t Length, bool IsFinal)
Parse a XML data stream.
Definition: xml_parser.cxx:175
XML_Parser xml_parser_
Definition: xml_parser.hxx:95
const char * name
std::map< string_t, string_t > xml_tag_attribute_container_t
void * p
int i
Length
#define COLON
static void xml_character_data_handler(void *UserData, const XML_Char *s, int len)
Definition: xml_parser.cxx:124
static void xml_start_element_handler(void *UserData, const XML_Char *name, const XML_Char **atts)
Definition: xml_parser.cxx:90
static void xml_comment_handler(void *UserData, const XML_Char *Data)
Definition: xml_parser.cxx:139
#define UTF8ToWString(s)
Definition: xml_parser.cxx:27
static void xml_end_element_handler(void *UserData, const XML_Char *name)
Definition: xml_parser.cxx:114