1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "internal/xml_parser.hxx"
22 #include "internal/i_xml_parser_event_handler.hxx"
25 #include "internal/utilities.hxx"
27 #define UTF8ToWString(s) s
32 namespace /* private */
35 /* Extracts the local part of tag without
36 namespace decoration e.g. meta:creator -> creator */
37 const XML_Char COLON
= (XML_Char
)':';
39 const XML_Char
* get_local_name(const XML_Char
* rawname
)
41 const XML_Char
* p
= rawname
;
46 // go back until the first ':'
47 while (*p
!= COLON
&& p
> rawname
)
50 // if we are on a colon one step forward
57 inline xml_parser
* get_parser_instance(void* data
)
59 return static_cast<xml_parser
*>(XML_GetUserData(
60 static_cast<XML_Parser
>(data
)));
63 bool has_only_whitespaces(const XML_Char
* s
, int len
)
65 const XML_Char
* p
= s
;
66 for (int i
= 0; i
< len
; i
++)
67 if (*p
++ != ' ') return false;
72 xml_parser::xml_parser(const XML_Char
* EncodingName
) :
74 xml_parser_(XML_ParserCreate(EncodingName
))
79 xml_parser::~xml_parser()
81 XML_ParserFree(xml_parser_
);
84 /* Callback functions will be called by the parser on
90 static void xml_start_element_handler(void* UserData
, const XML_Char
* name
, const XML_Char
** atts
)
92 assert(UserData
!= NULL
);
94 xml_parser
* pImpl
= get_parser_instance(UserData
);
96 i_xml_parser_event_handler
* pDocHdl
= pImpl
->get_document_handler();
99 xml_tag_attribute_container_t attributes
;
105 attributes
[UTF8ToWString(reinterpret_cast<const char*>(get_local_name(atts
[i
])))] = UTF8ToWString(reinterpret_cast<const char*>(atts
[i
+1]));
106 i
+= 2; // skip to next pair
109 pDocHdl
->start_element(
110 UTF8ToWString(reinterpret_cast<const char*>(name
)), UTF8ToWString(reinterpret_cast<const char*>(get_local_name(name
))), attributes
);
114 static void xml_end_element_handler(void* UserData
, const XML_Char
* name
)
118 xml_parser
* pImpl
= get_parser_instance(UserData
);
119 i_xml_parser_event_handler
* pDocHdl
= pImpl
->get_document_handler();
121 pDocHdl
->end_element(UTF8ToWString(reinterpret_cast<const char*>(name
)), UTF8ToWString(reinterpret_cast<const char*>(get_local_name(name
))));
124 static void xml_character_data_handler(void* UserData
, const XML_Char
* s
, int len
)
128 xml_parser
* pImpl
= get_parser_instance(UserData
);
129 i_xml_parser_event_handler
* pDocHdl
= pImpl
->get_document_handler();
132 if (has_only_whitespaces(s
,len
))
133 pDocHdl
->ignore_whitespace(UTF8ToWString(std::string(reinterpret_cast<const char*>(s
), len
)));
135 pDocHdl
->characters(UTF8ToWString(std::string(reinterpret_cast<const char*>(s
), len
)));
139 static void xml_comment_handler(void* UserData
, const XML_Char
* Data
)
143 xml_parser
* pImpl
= get_parser_instance(UserData
);
144 i_xml_parser_event_handler
* pDocHdl
= pImpl
->get_document_handler();
146 pDocHdl
->comment(UTF8ToWString(reinterpret_cast<const char*>(Data
)));
151 void xml_parser::init()
153 XML_SetUserData(xml_parser_
, this);
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_
);
161 XML_SetElementHandler(
163 xml_start_element_handler
,
164 xml_end_element_handler
);
166 XML_SetCharacterDataHandler(
168 xml_character_data_handler
);
170 XML_SetCommentHandler(
172 xml_comment_handler
);
175 void xml_parser::parse(const char* XmlData
, size_t Length
, bool IsFinal
)
177 if (XML_STATUS_ERROR
==
178 XML_Parse(xml_parser_
, XmlData
, static_cast<int>(Length
), IsFinal
))
180 throw xml_parser_exception(
181 XML_ErrorString(XML_GetErrorCode(xml_parser_
)),
182 (int)XML_GetErrorCode(xml_parser_
),
183 XML_GetCurrentLineNumber(xml_parser_
),
184 XML_GetCurrentColumnNumber(xml_parser_
),
185 XML_GetCurrentByteIndex(xml_parser_
));
189 void xml_parser::set_document_handler(
190 i_xml_parser_event_handler
* event_handler
)
192 document_handler_
= event_handler
;
196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */