Line data Source code
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 : #ifndef BOOTSTRP_XMLPARSE_HXX
21 : #define BOOTSTRP_XMLPARSE_HXX
22 :
23 : #include "sal/config.h"
24 :
25 : #include <cstddef>
26 : #include <vector>
27 :
28 : #include <signal.h>
29 :
30 : #include <libxml/xmlexports.h> // define XMLCALL so expat.h does not redefine it
31 : #include <expat.h>
32 :
33 : #include <rtl/ustring.hxx>
34 : #include <rtl/ustrbuf.hxx>
35 : #include "boost/unordered_map.hpp"
36 : #include "export.hxx"
37 :
38 : class XMLParentNode;
39 : class XMLElement;
40 :
41 :
42 : using namespace ::rtl;
43 : using namespace std;
44 :
45 : #define XML_NODE_TYPE_FILE 0x001
46 : #define XML_NODE_TYPE_ELEMENT 0x002
47 : #define XML_NODE_TYPE_DATA 0x003
48 : #define XML_NODE_TYPE_COMMENT 0x004
49 : #define XML_NODE_TYPE_DEFAULT 0x005
50 :
51 :
52 : //-------------------------------------------------------------------------
53 :
54 : /** Holds data of Attributes
55 : */
56 0 : class XMLAttribute
57 : {
58 : private:
59 : rtl::OUString sName;
60 : rtl::OUString sValue;
61 :
62 : public:
63 : /// creates an attribute
64 0 : XMLAttribute(
65 : const rtl::OUString &rName, // attributes name
66 : const rtl::OUString &rValue // attributes data
67 : )
68 0 : : sName( rName ), sValue( rValue ) {}
69 :
70 0 : rtl::OUString GetName() const { return sName; }
71 0 : rtl::OUString GetValue() const { return sValue; }
72 :
73 0 : void setValue(const rtl::OUString &rValue){sValue=rValue;}
74 :
75 : /// returns true if two attributes are equal and have the same value
76 : sal_Bool IsEqual(
77 : const XMLAttribute &rAttribute // the attribute which has to be equal
78 : )
79 : {
80 : return (( rAttribute.sName == sName ) && ( rAttribute.sValue == sValue ));
81 : }
82 : };
83 :
84 : typedef std::vector< XMLAttribute* > XMLAttributeList;
85 :
86 : //-------------------------------------------------------------------------
87 :
88 : /** Virtual base to handle different kinds of XML nodes
89 : */
90 0 : class XMLNode
91 : {
92 : protected:
93 0 : XMLNode() {}
94 :
95 : public:
96 : virtual sal_uInt16 GetNodeType() = 0;
97 0 : virtual ~XMLNode() {}
98 : };
99 :
100 : //-------------------------------------------------------------------------
101 :
102 : /** Virtual base to handle different kinds of child nodes
103 : */
104 : class XMLChildNode : public XMLNode
105 : {
106 : private:
107 : XMLParentNode *pParent;
108 :
109 : protected:
110 : XMLChildNode( XMLParentNode *pPar );
111 : XMLChildNode():pParent( NULL ){};
112 : XMLChildNode( const XMLChildNode& obj);
113 : XMLChildNode& operator=(const XMLChildNode& obj);
114 : public:
115 : virtual sal_uInt16 GetNodeType() = 0;
116 :
117 : /// returns the parent of this node
118 0 : XMLParentNode *GetParent() { return pParent; }
119 0 : virtual ~XMLChildNode(){};
120 : };
121 :
122 : typedef std::vector< XMLChildNode* > XMLChildNodeList;
123 :
124 : //-------------------------------------------------------------------------
125 :
126 : /** Virtual base to handle different kinds of parent nodes
127 : */
128 : class XMLData;
129 :
130 : class XMLParentNode : public XMLChildNode
131 : {
132 : private:
133 : XMLChildNodeList* pChildList;
134 : static int dbgcnt;
135 :
136 : protected:
137 0 : XMLParentNode( XMLParentNode *pPar )
138 0 : : XMLChildNode( pPar ), pChildList( NULL )
139 : {
140 0 : }
141 : XMLParentNode(): pChildList(NULL){
142 : }
143 : /// Copyconstructor
144 : XMLParentNode( const XMLParentNode& );
145 :
146 : XMLParentNode& operator=(const XMLParentNode& obj);
147 : virtual ~XMLParentNode();
148 :
149 :
150 : public:
151 : virtual sal_uInt16 GetNodeType() = 0;
152 :
153 : /// returns child list of this node
154 0 : XMLChildNodeList *GetChildList() { return pChildList; }
155 :
156 : /// adds a new child
157 : void AddChild(
158 : XMLChildNode *pChild /// the new child
159 : );
160 :
161 : void RemoveAndDeleteAllChildren();
162 : };
163 :
164 : //-------------------------------------------------------------------------
165 :
166 : /// Mapping numeric Language code <-> XML Element
167 : typedef boost::unordered_map<rtl::OString, XMLElement*, rtl::OStringHash> LangHashMap;
168 :
169 : /// Mapping XML Element string identifier <-> Language Map
170 : typedef boost::unordered_map<rtl::OString, LangHashMap*, rtl::OStringHash> XMLHashMap;
171 :
172 : /// Mapping iso alpha string code <-> iso numeric code
173 : typedef boost::unordered_map<rtl::OString, int, rtl::OStringHash> HashMap;
174 :
175 : /// Mapping XML tag names <-> have localizable strings
176 : typedef boost::unordered_map<rtl::OString, sal_Bool, rtl::OStringHash> TagMap;
177 :
178 : /** Holds information of a XML file, is root node of tree
179 : */
180 :
181 :
182 : class XMLFile : public XMLParentNode
183 : {
184 : public:
185 : XMLFile(
186 : const rtl::OUString &rFileName // the file name, empty if created from memory stream
187 : );
188 : XMLFile( const XMLFile& obj ) ;
189 : ~XMLFile();
190 :
191 : void Print( XMLNode *pCur = NULL, sal_uInt16 nLevel = 0 );
192 : virtual void SearchL10NElements( XMLParentNode *pCur, int pos = 0 );
193 : void Extract( XMLFile *pCur = NULL );
194 :
195 0 : XMLHashMap* GetStrings(){return XMLStrings;}
196 : void Write( rtl::OString const &rFilename );
197 : sal_Bool Write( ofstream &rStream , XMLNode *pCur = NULL );
198 :
199 : bool CheckExportStatus( XMLParentNode *pCur = NULL );// , int pos = 0 );
200 :
201 : XMLFile& operator=(const XMLFile& obj);
202 :
203 : virtual sal_uInt16 GetNodeType();
204 :
205 : /// returns file name
206 0 : rtl::OUString GetName() { return sFileName; }
207 0 : void SetName( const rtl::OUString &rFilename ) { sFileName = rFilename; }
208 0 : const std::vector<rtl::OString> getOrder(){ return order; }
209 :
210 : protected:
211 : // writes a string as UTF8 with dos line ends to a given stream
212 : void WriteString( ofstream &rStream, const rtl::OUString &sString );
213 :
214 : void InsertL10NElement( XMLElement* pElement);
215 :
216 : // DATA
217 : rtl::OUString sFileName;
218 :
219 : const rtl::OString ID, OLDREF, XML_LANG;
220 :
221 : TagMap nodes_localize;
222 : XMLHashMap* XMLStrings;
223 :
224 : std::vector <rtl::OString> order;
225 : };
226 :
227 : /// An Utility class for XML
228 : /// See RFC 3066 / #i8252# for ISO codes
229 : class XMLUtil{
230 :
231 : public:
232 : /// Quot the XML characters and replace \n \t
233 : static void QuotHTML( rtl::OUString &rString );
234 :
235 : /// UnQuot the XML characters and restore \n \t
236 : static void UnQuotHTML ( rtl::OUString &rString );
237 : };
238 :
239 :
240 :
241 : //-------------------------------------------------------------------------
242 :
243 : /** Hold information of an element node
244 : */
245 : class XMLElement : public XMLParentNode
246 : {
247 : private:
248 : rtl::OUString sElementName;
249 : XMLAttributeList *pAttributes;
250 : rtl::OString project,
251 : filename,
252 : id,
253 : sOldRef,
254 : resourceType,
255 : languageId;
256 : int nPos;
257 :
258 : protected:
259 : void Print(XMLNode *pCur, OUStringBuffer& buffer , bool rootelement);
260 : public:
261 : /// create a element node
262 : XMLElement(){}
263 0 : XMLElement(
264 : const rtl::OUString &rName, // the element name
265 : XMLParentNode *Parent // parent node of this element
266 : ): XMLParentNode( Parent ),
267 : sElementName( rName ),
268 : pAttributes( NULL ),
269 : project(""),
270 : filename(""),
271 : id(""),
272 : sOldRef(""),
273 : resourceType(""),
274 : languageId(""),
275 0 : nPos(0)
276 : {
277 0 : }
278 : ~XMLElement();
279 : XMLElement(const XMLElement&);
280 :
281 : XMLElement& operator=(const XMLElement& obj);
282 : /// returns node type XML_NODE_ELEMENT
283 : virtual sal_uInt16 GetNodeType();
284 :
285 : /// returns element name
286 0 : rtl::OUString GetName() { return sElementName; }
287 :
288 : /// returns list of attributes of this element
289 0 : XMLAttributeList *GetAttributeList() { return pAttributes; }
290 :
291 : /// adds a new attribute to this element, typically used by parser
292 : void AddAttribute( const rtl::OUString &rAttribute, const rtl::OUString &rValue );
293 :
294 : void ChangeLanguageTag( const rtl::OUString &rValue );
295 :
296 : // Return a Unicode String representation of this object
297 : OUString ToOUString();
298 :
299 : void SetProject ( rtl::OString const & prj ){ project = prj; }
300 : void SetFileName ( rtl::OString const & fn ){ filename = fn; }
301 0 : void SetId ( rtl::OString const & theId ){ id = theId; }
302 : void SetResourceType ( rtl::OString const & rt ){ resourceType = rt; }
303 0 : void SetLanguageId ( rtl::OString const & lid ){ languageId = lid; }
304 0 : void SetPos ( int nPos_in ){ nPos = nPos_in; }
305 0 : void SetOldRef ( rtl::OString const & sOldRef_in ){ sOldRef = sOldRef_in; }
306 :
307 0 : virtual int GetPos() { return nPos; }
308 : rtl::OString GetProject() { return project; }
309 : rtl::OString GetFileName() { return filename; }
310 : rtl::OString GetId() { return id; }
311 0 : rtl::OString GetOldref() { return sOldRef; }
312 : rtl::OString GetResourceType(){ return resourceType; }
313 : rtl::OString GetLanguageId() { return languageId; }
314 :
315 :
316 : };
317 : //-------------------------------------------------------------------------
318 :
319 :
320 : /** Holds character data
321 : */
322 0 : class XMLData : public XMLChildNode
323 : {
324 : private:
325 : rtl::OUString sData;
326 : bool isNewCreated;
327 :
328 : public:
329 : /// create a data node
330 0 : XMLData(
331 : const rtl::OUString &rData, // the initial data
332 : XMLParentNode *Parent // the parent node of this data, typically a element node
333 : )
334 0 : : XMLChildNode( Parent ), sData( rData ) , isNewCreated ( false ){}
335 0 : XMLData(
336 : const rtl::OUString &rData, // the initial data
337 : XMLParentNode *Parent, // the parent node of this data, typically a element node
338 : bool newCreated
339 : )
340 0 : : XMLChildNode( Parent ), sData( rData ) , isNewCreated ( newCreated ){}
341 :
342 : XMLData(const XMLData& obj);
343 :
344 : XMLData& operator=(const XMLData& obj);
345 : virtual sal_uInt16 GetNodeType();
346 :
347 : /// returns the data
348 0 : rtl::OUString GetData() { return sData; }
349 :
350 : bool isNew() { return isNewCreated; }
351 : /// adds new character data to the existing one
352 : void AddData(
353 : const rtl::OUString &rData // the new data
354 : );
355 :
356 :
357 :
358 : };
359 :
360 : //-------------------------------------------------------------------------
361 :
362 : /** Holds comments
363 : */
364 0 : class XMLComment : public XMLChildNode
365 : {
366 : private:
367 : rtl::OUString sComment;
368 :
369 : public:
370 : /// create a comment node
371 0 : XMLComment(
372 : const rtl::OUString &rComment, // the comment
373 : XMLParentNode *Parent // the parent node of this comemnt, typically a element node
374 : )
375 0 : : XMLChildNode( Parent ), sComment( rComment ) {}
376 :
377 : virtual sal_uInt16 GetNodeType();
378 :
379 : XMLComment( const XMLComment& obj );
380 :
381 : XMLComment& operator=(const XMLComment& obj);
382 :
383 : /// returns the comment
384 0 : rtl::OUString GetComment() { return sComment; }
385 : };
386 :
387 : //-------------------------------------------------------------------------
388 :
389 : /** Holds additional file content like those for which no handler exists
390 : */
391 0 : class XMLDefault : public XMLChildNode
392 : {
393 : private:
394 : rtl::OUString sDefault;
395 :
396 : public:
397 : /// create a comment node
398 0 : XMLDefault(
399 : const rtl::OUString &rDefault, // the comment
400 : XMLParentNode *Parent // the parent node of this comemnt, typically a element node
401 : )
402 0 : : XMLChildNode( Parent ), sDefault( rDefault ) {}
403 :
404 : XMLDefault(const XMLDefault& obj);
405 :
406 : XMLDefault& operator=(const XMLDefault& obj);
407 :
408 : /// returns node type XML_NODE_TYPE_COMMENT
409 : virtual sal_uInt16 GetNodeType();
410 :
411 : /// returns the comment
412 0 : rtl::OUString GetDefault() { return sDefault; }
413 : };
414 :
415 : //-------------------------------------------------------------------------
416 :
417 : /** struct for error information, used by class SimpleXMLParser
418 : */
419 0 : struct XMLError {
420 : XML_Error eCode; // the error code
421 : std::size_t nLine; // error line number
422 : std::size_t nColumn; // error column number
423 : rtl::OUString sMessage; // readable error message
424 : };
425 :
426 : //-------------------------------------------------------------------------
427 :
428 : /** validating xml parser, creates a document tree with xml nodes
429 : */
430 :
431 :
432 : class SimpleXMLParser
433 : {
434 : private:
435 : XML_Parser aParser;
436 : XMLError aErrorInformation;
437 :
438 : XMLFile *pXMLFile;
439 : XMLParentNode *pCurNode;
440 : XMLData *pCurData;
441 :
442 :
443 : static void StartElementHandler( void *userData, const XML_Char *name, const XML_Char **atts );
444 : static void EndElementHandler( void *userData, const XML_Char *name );
445 : static void CharacterDataHandler( void *userData, const XML_Char *s, int len );
446 : static void CommentHandler( void *userData, const XML_Char *data );
447 : static void DefaultHandler( void *userData, const XML_Char *s, int len );
448 :
449 :
450 : void StartElement( const XML_Char *name, const XML_Char **atts );
451 : void EndElement( const XML_Char *name );
452 : void CharacterData( const XML_Char *s, int len );
453 : void Comment( const XML_Char *data );
454 : void Default( const XML_Char *s, int len );
455 :
456 : public:
457 : /// creates a new parser
458 : SimpleXMLParser();
459 : ~SimpleXMLParser();
460 :
461 : /// parse a file, returns NULL on criticall errors
462 : XMLFile *Execute(
463 : const rtl::OUString &rFileName, // the file name
464 : XMLFile *pXMLFileIn // the XMLFile
465 : );
466 :
467 : /// returns an error struct
468 0 : const XMLError &GetError() { return aErrorInformation; }
469 : };
470 :
471 : #endif
472 :
473 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|