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 .
19 #include "sal/config.h"
21 #include <iterator> /* std::iterator*/
25 #include <sal/alloca.h>
29 #include "xmlparse.hxx"
32 #include <osl/mutex.hxx>
33 #include <osl/thread.hxx>
34 #include <osl/process.h>
35 #include <rtl/strbuf.hxx>
36 #include <unicode/regex.h>
38 using namespace U_ICU_NAMESPACE
;
46 /*****************************************************************************/
47 XMLChildNode::XMLChildNode( XMLParentNode
*pPar
)
48 /*****************************************************************************/
52 pParent
->AddChild( this );
56 /*****************************************************************************/
57 XMLChildNode::XMLChildNode( const XMLChildNode
& obj
)
58 /*****************************************************************************/
60 pParent(obj
.pParent
){}
62 /*****************************************************************************/
63 XMLChildNode
& XMLChildNode::operator=(const XMLChildNode
& obj
){
64 /*****************************************************************************/
71 // class XMLParentNode
75 /*****************************************************************************/
76 XMLParentNode::~XMLParentNode()
77 /*****************************************************************************/
80 RemoveAndDeleteAllChildren();
86 /*****************************************************************************/
87 XMLParentNode::XMLParentNode( const XMLParentNode
& obj
)
88 /*****************************************************************************/
92 pChildList
=new XMLChildNodeList();
93 XMLChildNode
* pNode
= NULL
;
94 for ( size_t i
= 0; i
< obj
.pChildList
->size(); i
++ ){
95 pNode
= (*obj
.pChildList
)[ i
];
97 switch(pNode
->GetNodeType()){
98 case XML_NODE_TYPE_ELEMENT
:
99 AddChild( new XMLElement( *static_cast<XMLElement
* >(pNode
) ) ); break;
100 case XML_NODE_TYPE_DATA
:
101 AddChild( new XMLData ( *static_cast<XMLData
* > (pNode
) ) ); break;
102 case XML_NODE_TYPE_COMMENT
:
103 AddChild( new XMLComment( *static_cast<XMLComment
* >(pNode
) ) ); break;
104 case XML_NODE_TYPE_DEFAULT
:
105 AddChild( new XMLDefault( *static_cast<XMLDefault
* >(pNode
) ) ); break;
106 default: fprintf(stdout
,"XMLParentNode::XMLParentNode( const XMLParentNode& obj) strange obj");
110 }else pChildList
= NULL
;
112 /*****************************************************************************/
113 XMLParentNode
& XMLParentNode::operator=(const XMLParentNode
& obj
){
114 /*****************************************************************************/
116 XMLChildNode::operator=(obj
);
118 RemoveAndDeleteAllChildren();
122 if( obj
.pChildList
){
123 pChildList
=new XMLChildNodeList();
124 for ( size_t i
= 0; i
< obj
.pChildList
->size(); i
++ )
125 AddChild( (*obj
.pChildList
)[ i
] );
126 }else pChildList
= NULL
;
131 /*****************************************************************************/
132 void XMLParentNode::AddChild( XMLChildNode
*pChild
)
133 /*****************************************************************************/
136 pChildList
= new XMLChildNodeList();
137 pChildList
->push_back( pChild
);
140 /*****************************************************************************/
141 void XMLParentNode::RemoveAndDeleteAllChildren(){
142 /*****************************************************************************/
144 for ( size_t i
= 0; i
< pChildList
->size(); i
++ )
145 delete (*pChildList
)[ i
];
154 /*****************************************************************************/
155 sal_uInt16
XMLFile::GetNodeType()
156 /*****************************************************************************/
158 return XML_NODE_TYPE_FILE
;
161 void XMLFile::Write( OString
const &aFilename
)
164 aFilename
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
167 << "Error: helpex cannot create file " << aFilename
.getStr()
169 std::exit(EXIT_FAILURE
);
175 void XMLFile::WriteString( ofstream
&rStream
, const OUString
&sString
)
177 OString
sText(OUStringToOString(sString
, RTL_TEXTENCODING_UTF8
));
178 rStream
<< sText
.getStr();
181 sal_Bool
XMLFile::Write( ofstream
&rStream
, XMLNode
*pCur
)
184 Write( rStream
, this );
186 switch( pCur
->GetNodeType()) {
187 case XML_NODE_TYPE_FILE
: {
189 for ( size_t i
= 0; i
< GetChildList()->size(); i
++ )
190 Write( rStream
, (*GetChildList())[ i
] );
193 case XML_NODE_TYPE_ELEMENT
: {
194 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
196 WriteString( rStream
, pElement
->GetName());
197 if ( pElement
->GetAttributeList())
198 for ( size_t j
= 0; j
< pElement
->GetAttributeList()->size(); j
++ ) {
200 OUString
sData( (*pElement
->GetAttributeList())[ j
]->GetName() );
201 WriteString( rStream
, XMLUtil::QuotHTML( sData
) );
203 sData
= (*pElement
->GetAttributeList())[ j
]->GetValue();
204 WriteString( rStream
, XMLUtil::QuotHTML( sData
) );
207 if ( !pElement
->GetChildList())
211 for ( size_t k
= 0; k
< pElement
->GetChildList()->size(); k
++ )
212 Write( rStream
, (*pElement
->GetChildList())[ k
] );
214 WriteString( rStream
, pElement
->GetName());
219 case XML_NODE_TYPE_DATA
: {
220 XMLData
*pData
= ( XMLData
* ) pCur
;
221 OUString
sData( pData
->GetData());
222 WriteString( rStream
, XMLUtil::QuotHTML( sData
) );
225 case XML_NODE_TYPE_COMMENT
: {
226 XMLComment
*pComment
= ( XMLComment
* ) pCur
;
228 WriteString( rStream
, pComment
->GetComment());
232 case XML_NODE_TYPE_DEFAULT
: {
233 XMLDefault
*pDefault
= ( XMLDefault
* ) pCur
;
234 WriteString( rStream
, pDefault
->GetDefault());
243 void XMLFile::Print( XMLNode
*pCur
, sal_uInt16 nLevel
)
249 switch( pCur
->GetNodeType()) {
250 case XML_NODE_TYPE_FILE
: {
252 for ( size_t i
= 0; i
< GetChildList()->size(); i
++ )
253 Print( (*GetChildList())[ i
] );
256 case XML_NODE_TYPE_ELEMENT
: {
257 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
259 fprintf( stdout
, "<%s", OUStringToOString(pElement
->GetName(), RTL_TEXTENCODING_UTF8
).getStr());
260 if ( pElement
->GetAttributeList())
262 for (size_t j
= 0; j
< pElement
->GetAttributeList()->size(); ++j
)
264 OString
aAttrName(OUStringToOString((*pElement
->GetAttributeList())[j
]->GetName(),
265 RTL_TEXTENCODING_UTF8
));
266 if (!aAttrName
.equalsIgnoreAsciiCase(XML_LANG
))
268 fprintf( stdout
, " %s=\"%s\"",
270 OUStringToOString( (*pElement
->GetAttributeList())[ j
]->GetValue(),
271 RTL_TEXTENCODING_UTF8
).getStr());
275 if ( !pElement
->GetChildList())
276 fprintf( stdout
, "/>" );
278 fprintf( stdout
, ">" );
279 for ( size_t k
= 0; k
< pElement
->GetChildList()->size(); k
++ )
280 Print( (*pElement
->GetChildList())[ k
], nLevel
+ 1 );
281 fprintf( stdout
, "</%s>", OUStringToOString(pElement
->GetName(), RTL_TEXTENCODING_UTF8
).getStr());
285 case XML_NODE_TYPE_DATA
: {
286 XMLData
*pData
= ( XMLData
* ) pCur
;
287 OUString sData
= pData
->GetData();
288 fprintf( stdout
, "%s", OUStringToOString(sData
, RTL_TEXTENCODING_UTF8
).getStr());
291 case XML_NODE_TYPE_COMMENT
: {
292 XMLComment
*pComment
= ( XMLComment
* ) pCur
;
293 fprintf( stdout
, "<!--%s-->", OUStringToOString(pComment
->GetComment(), RTL_TEXTENCODING_UTF8
).getStr());
296 case XML_NODE_TYPE_DEFAULT
: {
297 XMLDefault
*pDefault
= ( XMLDefault
* ) pCur
;
298 fprintf( stdout
, "%s", OUStringToOString(pDefault
->GetDefault(), RTL_TEXTENCODING_UTF8
).getStr());
306 if( XMLStrings
!= NULL
){
307 XMLHashMap::iterator pos
= XMLStrings
->begin();
308 for( ; pos
!= XMLStrings
->end() ; ++pos
){
309 delete pos
->second
; // Check and delete content also ?
315 /*****************************************************************************/
316 XMLFile::XMLFile( const OUString
&rFileName
) // the file name, empty if created from memory stream
317 /*****************************************************************************/
318 : XMLParentNode( NULL
),
319 sFileName ( rFileName
),
322 XML_LANG ( "xml-lang" ),
326 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("bookmark")) , sal_True
) );
327 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("variable")) , sal_True
) );
328 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("paragraph")) , sal_True
) );
329 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("alt")) , sal_True
) );
330 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("caption")) , sal_True
) );
331 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("title")) , sal_True
) );
332 nodes_localize
.insert( TagMap::value_type(OString(RTL_CONSTASCII_STRINGPARAM("link")) , sal_True
) );
334 /*****************************************************************************/
335 void XMLFile::Extract( XMLFile
*pCur
)
336 /*****************************************************************************/
338 if( XMLStrings
!= NULL
) delete XMLStrings
; // Elements ?
340 XMLStrings
= new XMLHashMap();
342 SearchL10NElements( this );
344 if( pCur
->GetNodeType()==XML_NODE_TYPE_FILE
) {
345 SearchL10NElements(pCur
);
350 /*****************************************************************************/
351 void XMLFile::InsertL10NElement( XMLElement
* pElement
){
352 /*****************************************************************************/
353 OString tmpStr
,id
,language("");
356 if( pElement
->GetAttributeList() != NULL
){
357 for ( size_t j
= 0; j
< pElement
->GetAttributeList()->size(); j
++ )
359 tmpStr
=OUStringToOString((*pElement
->GetAttributeList())[ j
]->GetName(), RTL_TEXTENCODING_UTF8
);
360 if (tmpStr
== ID
) { // Get the "id" Attribute
361 id
= OUStringToOString((*pElement
->GetAttributeList())[ j
]->GetValue(),RTL_TEXTENCODING_UTF8
);
363 if (tmpStr
== XML_LANG
) { // Get the "xml-lang" Attribute
364 language
= OUStringToOString((*pElement
->GetAttributeList())[j
]->GetValue(),RTL_TEXTENCODING_UTF8
);
369 fprintf(stdout
,"XMLFile::InsertL10NElement: No AttributeList found");
370 fprintf(stdout
,"++++++++++++++++++++++++++++++++++++++++++++++++++");
371 Print( pElement
, 0 );
372 fprintf(stdout
,"++++++++++++++++++++++++++++++++++++++++++++++++++");
375 XMLHashMap::iterator pos
= XMLStrings
->find( id
);
376 if( pos
== XMLStrings
->end() ){ // No instanze , create new one
377 elem
= new LangHashMap();
378 (*elem
)[ language
]=pElement
;
379 XMLStrings
->insert( XMLHashMap::value_type( id
, elem
) );
380 order
.push_back( id
);
381 }else{ // Already there
383 if ( (*elem
)[ language
] )
385 fprintf(stdout
,"Error: Duplicated entry. ID = %s LANG = %s in File %s\n", id
.getStr(), language
.getStr(), OUStringToOString(sFileName
, RTL_TEXTENCODING_ASCII_US
).getStr() );
388 (*elem
)[ language
]=pElement
;
392 XMLFile::XMLFile( const XMLFile
& obj
)
393 /*****************************************************************************/
394 : XMLParentNode( obj
),
395 sFileName ( obj
.sFileName
),
398 XML_LANG ( "xml-lang" ),
403 nodes_localize
=obj
.nodes_localize
;
408 /*****************************************************************************/
409 XMLFile
& XMLFile::operator=(const XMLFile
& obj
){
410 /*****************************************************************************/
413 XMLParentNode::operator=(obj
);
415 nodes_localize
=obj
.nodes_localize
;
418 if( XMLStrings
) delete XMLStrings
;
422 XMLStrings
= new XMLHashMap();
423 for( XMLHashMap::iterator pos
= obj
.XMLStrings
->begin() ; pos
!= obj
.XMLStrings
->end() ; ++pos
)
425 LangHashMap
* elem
=pos
->second
;
426 LangHashMap
* newelem
= new LangHashMap();
427 for(LangHashMap::iterator pos2
=elem
->begin(); pos2
!=elem
->end();++pos2
){
428 (*newelem
)[ pos2
->first
] = new XMLElement( *pos2
->second
);
430 (*XMLStrings
)[ pos
->first
] = newelem
;
438 /*****************************************************************************/
439 void XMLFile::SearchL10NElements( XMLParentNode
*pCur
, int pos
)
440 /*****************************************************************************/
442 static const OString
LOCALIZE("localize");
443 static const OString
THEID("id");
446 SearchL10NElements( this );
448 switch( pCur
->GetNodeType()) {
449 case XML_NODE_TYPE_FILE
: {
450 XMLParentNode
* pElement
;
452 for ( size_t i
= 0; i
< GetChildList()->size(); i
++ ){
453 pElement
= (XMLParentNode
*) (*GetChildList())[ i
];
454 if( pElement
->GetNodeType() == XML_NODE_TYPE_ELEMENT
) SearchL10NElements( pElement
, i
);
459 case XML_NODE_TYPE_ELEMENT
: {
460 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
461 OString
sName(OUStringToOString(pElement
->GetName(), RTL_TEXTENCODING_ASCII_US
).toAsciiLowerCase());
462 OString language
,tmpStrVal
,oldref
;
463 if ( pElement
->GetAttributeList())
465 for ( size_t j
= 0 , cnt
= pElement
->GetAttributeList()->size(); j
< cnt
&& bInsert
; ++j
)
467 const OString tmpStr
= OUStringToOString((*pElement
->GetAttributeList())[j
]->GetName(), RTL_TEXTENCODING_UTF8
);
468 if (tmpStr
== THEID
) { // Get the "id" Attribute
469 tmpStrVal
=OUStringToOString( (*pElement
->GetAttributeList())[ j
]->GetValue(),RTL_TEXTENCODING_UTF8
);
471 if (tmpStr
== LOCALIZE
) { // Get the "localize" Attribute
474 if (tmpStr
== XML_LANG
) { // Get the "xml-lang" Attribute
475 language
=OUStringToOString( (*pElement
->GetAttributeList())[ j
]->GetValue(),RTL_TEXTENCODING_UTF8
);
477 if (tmpStr
== OLDREF
) { // Get the "oldref" Attribute
478 oldref
=OUStringToOString( (*pElement
->GetAttributeList())[ j
]->GetValue(),RTL_TEXTENCODING_UTF8
);
481 pElement
->SetLanguageId ( language
);
482 pElement
->SetId(tmpStrVal
);
483 pElement
->SetOldRef ( oldref
);
484 pElement
->SetPos( pos
);
487 if ( bInsert
&& ( nodes_localize
.find( sName
) != nodes_localize
.end() ) )
488 InsertL10NElement(pElement
);
489 else if ( bInsert
&& pElement
->GetChildList() ){
490 for ( size_t k
= 0; k
< pElement
->GetChildList()->size(); k
++ )
491 SearchL10NElements( (XMLParentNode
*)(*pElement
->GetChildList())[ k
], k
);
495 case XML_NODE_TYPE_DATA
: {
498 case XML_NODE_TYPE_COMMENT
: {
501 case XML_NODE_TYPE_DEFAULT
: {
508 /*****************************************************************************/
509 bool XMLFile::CheckExportStatus( XMLParentNode
*pCur
)
510 /*****************************************************************************/
512 static bool bStatusExport
= true;
513 const OString
STATUS(RTL_CONSTASCII_STRINGPARAM("status"));
514 const OString
PUBLISH(RTL_CONSTASCII_STRINGPARAM("PUBLISH"));
515 const OString
DEPRECATED(RTL_CONSTASCII_STRINGPARAM("DEPRECATED"));
516 const OString
TOPIC(RTL_CONSTASCII_STRINGPARAM("topic"));
520 CheckExportStatus( this );
522 switch( pCur
->GetNodeType()) {
523 case XML_NODE_TYPE_FILE
: {
524 XMLParentNode
* pElement
;
526 for ( size_t i
= 0; i
< GetChildList()->size(); i
++ ){
527 pElement
= (XMLParentNode
*)(*GetChildList())[ i
];
528 if( pElement
->GetNodeType() == XML_NODE_TYPE_ELEMENT
) CheckExportStatus( pElement
);//, i);
533 case XML_NODE_TYPE_ELEMENT
: {
534 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
535 OString
sName(OUStringToOString(pElement
->GetName(), RTL_TEXTENCODING_ASCII_US
));
536 if (sName
.equalsIgnoreAsciiCase(TOPIC
))
538 if ( pElement
->GetAttributeList())
540 for (size_t j
= 0 , cnt
= pElement
->GetAttributeList()->size(); j
< cnt
&& bInsert
; ++j
)
542 const OString
tmpStr(OUStringToOString((*pElement
->GetAttributeList())[j
]->GetName(),
543 RTL_TEXTENCODING_UTF8
));
544 if (tmpStr
.equalsIgnoreAsciiCase(STATUS
))
546 OString
tmpStrVal(OUStringToOString( (*pElement
->GetAttributeList())[j
]->GetValue(),
547 RTL_TEXTENCODING_UTF8
));
548 if (!tmpStrVal
.equalsIgnoreAsciiCase(PUBLISH
) &&
549 !tmpStrVal
.equalsIgnoreAsciiCase(DEPRECATED
))
551 bStatusExport
= false;
558 else if ( pElement
->GetChildList() )
560 for (size_t k
= 0; k
< pElement
->GetChildList()->size(); ++k
)
561 CheckExportStatus( (XMLParentNode
*)(*pElement
->GetChildList())[k
] );
567 return bStatusExport
;
570 /*****************************************************************************/
571 sal_uInt16
XMLElement::GetNodeType()
572 /*****************************************************************************/
574 return XML_NODE_TYPE_ELEMENT
;
577 /*****************************************************************************/
578 XMLElement::XMLElement(const XMLElement
& obj
)
579 /*****************************************************************************/
581 XMLParentNode ( obj
),
582 sElementName ( obj
.sElementName
),
583 pAttributes ( NULL
),
584 project ( obj
.project
),
585 filename ( obj
.filename
),
587 sOldRef ( obj
.sOldRef
),
588 resourceType ( obj
.resourceType
),
589 languageId ( obj
.languageId
),
593 if ( obj
.pAttributes
){
594 pAttributes
= new XMLAttributeList();
595 for ( size_t i
= 0; i
< obj
.pAttributes
->size(); i
++ )
596 AddAttribute( (*obj
.pAttributes
)[ i
]->GetName(), (*obj
.pAttributes
)[ i
]->GetValue() );
600 /*****************************************************************************/
601 XMLElement
& XMLElement::operator=(const XMLElement
& obj
){
602 /*****************************************************************************/
604 XMLParentNode::operator=(obj
);
605 sElementName
=obj
.sElementName
;
606 project
=obj
.project
;
607 filename
=obj
.filename
;
609 sOldRef
=obj
.sOldRef
;
610 resourceType
=obj
.resourceType
;
611 languageId
=obj
.languageId
;
615 for ( size_t i
= 0; i
< pAttributes
->size(); i
++ )
616 delete (*pAttributes
)[ i
];
619 if ( obj
.pAttributes
){
620 pAttributes
=new XMLAttributeList();
621 for ( size_t i
= 0; i
< obj
.pAttributes
->size(); i
++ )
622 AddAttribute( (*obj
.pAttributes
)[ i
]->GetName(), (*obj
.pAttributes
)[ i
]->GetValue() );
628 /*****************************************************************************/
629 void XMLElement::AddAttribute( const OUString
&rAttribute
, const OUString
&rValue
)
630 /*****************************************************************************/
633 pAttributes
= new XMLAttributeList();
634 pAttributes
->push_back( new XMLAttribute( rAttribute
, rValue
) );
637 /*****************************************************************************/
638 void XMLElement::ChangeLanguageTag( const OUString
&rValue
)
640 SetLanguageId(OUStringToOString(rValue
, RTL_TEXTENCODING_UTF8
));
643 for (size_t i
= 0; i
< pAttributes
->size(); ++i
)
645 if ( (*pAttributes
)[ i
]->GetName() == "xml-lang" )
646 (*pAttributes
)[ i
]->setValue(rValue
);
649 XMLChildNode
* pNode
= NULL
;
650 XMLElement
* pElem
= NULL
;
651 XMLChildNodeList
* pCList
= GetChildList();
655 for ( size_t i
= 0; i
< pCList
->size(); i
++ )
657 pNode
= (*pCList
)[ i
];
658 if( pNode
!= NULL
&& pNode
->GetNodeType() == XML_NODE_TYPE_ELEMENT
)
660 pElem
= static_cast< XMLElement
* >(pNode
);
661 pElem
->ChangeLanguageTag( rValue
);
662 pElem
->SetLanguageId(OUStringToOString(rValue
, RTL_TEXTENCODING_UTF8
));
671 /*****************************************************************************/
672 XMLElement::~XMLElement()
673 /*****************************************************************************/
676 for ( size_t i
= 0; i
< pAttributes
->size(); i
++ )
677 delete (*pAttributes
)[ i
];
684 /*****************************************************************************/
685 OUString
XMLElement::ToOUString(){
686 /*****************************************************************************/
687 OUStringBuffer
* buffer
= new OUStringBuffer();
688 Print(this,*buffer
,true);
689 OUString result
=buffer
->makeStringAndClear();
690 OUString
xy(result
.getStr());
695 /*****************************************************************************/
696 void XMLElement::Print(XMLNode
*pCur
, OUStringBuffer
& buffer
, bool rootelement
){
697 /*****************************************************************************/
698 static const OUString
XML_LANG ( "xml-lang" );
702 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
703 if ( pElement
->GetAttributeList()){
704 if ( pElement
->GetChildList()){
705 XMLChildNode
* tmp
=NULL
;
706 for ( size_t k
= 0; k
< pElement
->GetChildList()->size(); k
++ ){
707 tmp
= (*pElement
->GetChildList())[ k
];
708 Print( tmp
, buffer
, false);
715 switch( pCur
->GetNodeType()) {
716 case XML_NODE_TYPE_ELEMENT
: {
717 XMLElement
*pElement
= ( XMLElement
* ) pCur
;
719 if( !pElement
->GetName().equalsIgnoreAsciiCase("comment") ){
720 buffer
.append( OUString("<") );
721 buffer
.append( pElement
->GetName() );
722 if ( pElement
->GetAttributeList()){
723 for ( size_t j
= 0; j
< pElement
->GetAttributeList()->size(); j
++ ){
725 OUString
aAttrName( (*pElement
->GetAttributeList())[ j
]->GetName() );
726 if( !aAttrName
.equalsIgnoreAsciiCase( XML_LANG
) ) {
727 buffer
.append( OUString(" ") );
728 buffer
.append( aAttrName
);
729 buffer
.append( OUString("=") );
730 buffer
.append( OUString("\"") );
731 buffer
.append( (*pElement
->GetAttributeList())[ j
]->GetValue() );
732 buffer
.append( OUString("\"") );
736 if ( !pElement
->GetChildList())
737 buffer
.append( OUString("/>") );
739 buffer
.append( OUString(">") );
740 XMLChildNode
* tmp
=NULL
;
741 for ( size_t k
= 0; k
< pElement
->GetChildList()->size(); k
++ ){
742 tmp
= (*pElement
->GetChildList())[ k
];
743 Print( tmp
, buffer
, false);
745 buffer
.append( OUString("</") );
746 buffer
.append( pElement
->GetName() );
747 buffer
.append( OUString(">") );
752 case XML_NODE_TYPE_DATA
: {
753 XMLData
*pData
= ( XMLData
* ) pCur
;
754 OUString sData
= pData
->GetData();
755 buffer
.append( sData
);
758 case XML_NODE_TYPE_COMMENT
: {
759 XMLComment
*pComment
= ( XMLComment
* ) pCur
;
760 buffer
.append( OUString("<!--") );
761 buffer
.append( pComment
->GetComment() );
762 buffer
.append( OUString("-->") );
765 case XML_NODE_TYPE_DEFAULT
: {
766 XMLDefault
*pDefault
= ( XMLDefault
* ) pCur
;
767 buffer
.append( pDefault
->GetDefault() );
773 fprintf(stdout
,"\n#+------Error: NULL Pointer in XMLELement::Print------+#\n");
782 /*****************************************************************************/
783 XMLData::XMLData(const XMLData
& obj
)
784 /*****************************************************************************/
785 : XMLChildNode( obj
),
787 isNewCreated ( obj
.isNewCreated
){}
789 /*****************************************************************************/
790 XMLData
& XMLData::operator=(const XMLData
& obj
){
791 /*****************************************************************************/
793 XMLChildNode::operator=( obj
);
795 isNewCreated
= obj
.isNewCreated
;
799 /*****************************************************************************/
800 void XMLData::AddData( const OUString
&rData
) {
801 /*****************************************************************************/
805 /*****************************************************************************/
806 sal_uInt16
XMLData::GetNodeType()
807 /*****************************************************************************/
809 return XML_NODE_TYPE_DATA
;
816 /*****************************************************************************/
817 sal_uInt16
XMLComment::GetNodeType()
818 /*****************************************************************************/
820 return XML_NODE_TYPE_COMMENT
;
822 /*****************************************************************************/
823 XMLComment::XMLComment(const XMLComment
& obj
)
824 /*****************************************************************************/
825 : XMLChildNode( obj
),
826 sComment( obj
.sComment
){}
828 /*****************************************************************************/
829 XMLComment
& XMLComment::operator=(const XMLComment
& obj
){
830 /*****************************************************************************/
832 XMLChildNode::operator=( obj
);
833 sComment
= obj
.sComment
;
842 /*****************************************************************************/
843 sal_uInt16
XMLDefault::GetNodeType()
844 /*****************************************************************************/
846 return XML_NODE_TYPE_DEFAULT
;
848 /*****************************************************************************/
849 XMLDefault::XMLDefault(const XMLDefault
& obj
)
850 /*****************************************************************************/
851 : XMLChildNode( obj
),
852 sDefault( obj
.sDefault
){}
854 /*****************************************************************************/
855 XMLDefault
& XMLDefault::operator=(const XMLDefault
& obj
){
856 /*****************************************************************************/
858 XMLChildNode::operator=( obj
);
859 sDefault
= obj
.sDefault
;
866 // class SimpleXMLParser
869 #define XML_CHAR_TO_OUSTRING(x) OStringToOUString(OString(x), RTL_TEXTENCODING_UTF8)
870 #define XML_CHAR_N_TO_OUSTRING(x,n) OStringToOUString(OString(x,n), RTL_TEXTENCODING_UTF8 )
875 static OUString
lcl_pathnameToAbsoluteUrl(const OUString
& rPathname
) {
877 if (osl::FileBase::getFileURLFromSystemPath(rPathname
, sUrl
)
878 != osl::FileBase::E_None
)
880 std::cerr
<< "Error: Cannot convert input pathname to URL\n";
881 std::exit(EXIT_FAILURE
);
884 if (osl_getProcessWorkingDir(&sCwd
.pData
) != osl_Process_E_None
) {
885 std::cerr
<< "Error: Cannot determine cwd\n";
886 std::exit(EXIT_FAILURE
);
888 if (osl::FileBase::getAbsoluteFileURL(sCwd
, sUrl
, sUrl
)
889 != osl::FileBase::E_None
)
891 std::cerr
<< "Error: Cannot convert input URL to absolute URL\n";
892 std::exit(EXIT_FAILURE
);
899 /*****************************************************************************/
900 SimpleXMLParser::SimpleXMLParser()
901 /*****************************************************************************/
904 aParser
= XML_ParserCreate( NULL
);
905 XML_SetUserData( aParser
, this );
906 XML_SetElementHandler( aParser
, (XML_StartElementHandler
) StartElementHandler
, (XML_EndElementHandler
) EndElementHandler
);
907 XML_SetCharacterDataHandler( aParser
, (XML_CharacterDataHandler
) CharacterDataHandler
);
908 XML_SetCommentHandler( aParser
, (XML_CommentHandler
) CommentHandler
);
909 XML_SetDefaultHandler( aParser
, (XML_DefaultHandler
) DefaultHandler
);
912 /*****************************************************************************/
913 SimpleXMLParser::~SimpleXMLParser()
914 /*****************************************************************************/
916 XML_ParserFree( aParser
);
919 /*****************************************************************************/
920 void SimpleXMLParser::StartElementHandler(
921 void *userData
, const XML_Char
*name
, const XML_Char
**atts
)
922 /*****************************************************************************/
924 (( SimpleXMLParser
* ) userData
)->StartElement( name
, atts
);
928 /*****************************************************************************/
929 void SimpleXMLParser::EndElementHandler(
930 void *userData
, const XML_Char
*name
)
931 /*****************************************************************************/
933 (( SimpleXMLParser
* ) userData
)->EndElement( name
);
936 /*****************************************************************************/
937 void SimpleXMLParser::CharacterDataHandler(
938 void *userData
, const XML_Char
*s
, int len
)
939 /*****************************************************************************/
941 (( SimpleXMLParser
* ) userData
)->CharacterData( s
, len
);
944 /*****************************************************************************/
945 void SimpleXMLParser::CommentHandler(
946 void *userData
, const XML_Char
*data
)
947 /*****************************************************************************/
949 (( SimpleXMLParser
* ) userData
)->Comment( data
);
952 /*****************************************************************************/
953 void SimpleXMLParser::DefaultHandler(
954 void *userData
, const XML_Char
*s
, int len
)
955 /*****************************************************************************/
957 (( SimpleXMLParser
* ) userData
)->Default( s
, len
);
960 /*****************************************************************************/
961 void SimpleXMLParser::StartElement(
962 const XML_Char
*name
, const XML_Char
**atts
)
963 /*****************************************************************************/
965 OUString sElementName
= OUString( XML_CHAR_TO_OUSTRING( name
));
966 XMLElement
*pElement
= new XMLElement( sElementName
, ( XMLParentNode
* ) pCurNode
);
972 pElement
->AddAttribute(
973 OUString( XML_CHAR_TO_OUSTRING( atts
[ i
] )),
974 OUString( XML_CHAR_TO_OUSTRING( atts
[ i
+ 1 ] )));
979 /*****************************************************************************/
980 void SimpleXMLParser::EndElement( const XML_Char
*name
)
981 /*****************************************************************************/
983 // This variable is not used at all, but the sax C interface can't be changed
984 // To prevent warnings this dummy assignment is used
988 pCurNode
= pCurNode
->GetParent();
992 /*****************************************************************************/
993 void SimpleXMLParser::CharacterData(
994 const XML_Char
*s
, int len
)
995 /*****************************************************************************/
998 OUString x
= XML_CHAR_N_TO_OUSTRING( s
, len
);
999 XMLUtil::UnQuotHTML(x
);
1000 pCurData
= new XMLData( x
, pCurNode
);
1002 OUString x
= XML_CHAR_N_TO_OUSTRING( s
, len
);
1003 XMLUtil::UnQuotHTML(x
);
1004 pCurData
->AddData( x
);
1009 /*****************************************************************************/
1010 void SimpleXMLParser::Comment(
1011 const XML_Char
*data
)
1012 /*****************************************************************************/
1015 new XMLComment( OUString( XML_CHAR_TO_OUSTRING( data
)), pCurNode
);
1018 /*****************************************************************************/
1019 void SimpleXMLParser::Default(
1020 const XML_Char
*s
, int len
)
1021 /*****************************************************************************/
1025 OUString( XML_CHAR_N_TO_OUSTRING( s
, len
)), pCurNode
);
1028 /*****************************************************************************/
1029 XMLFile
*SimpleXMLParser::Execute( const OUString
&rFileName
, XMLFile
* pXMLFileIn
)
1030 /*****************************************************************************/
1032 aErrorInformation
.eCode
= XML_ERROR_NONE
;
1033 aErrorInformation
.nLine
= 0;
1034 aErrorInformation
.nColumn
= 0;
1035 aErrorInformation
.sMessage
= OUString( "ERROR: Unable to open file ");
1036 aErrorInformation
.sMessage
+= rFileName
;
1038 OUString
aFileURL(lcl_pathnameToAbsoluteUrl(rFileName
));
1041 if (osl_openFile(aFileURL
.pData
, &h
, osl_File_OpenFlag_Read
)
1048 oslFileError e
= osl_getFileSize(h
, &s
);
1050 if (e
== osl_File_E_None
) {
1051 e
= osl_mapFile(h
, &p
, s
, 0, 0);
1053 if (e
!= osl_File_E_None
) {
1058 pXMLFile
= pXMLFileIn
;
1059 pXMLFile
->SetName( rFileName
);
1061 pCurNode
= pXMLFile
;
1064 aErrorInformation
.eCode
= XML_ERROR_NONE
;
1065 aErrorInformation
.nLine
= 0;
1066 aErrorInformation
.nColumn
= 0;
1067 if ( !pXMLFile
->GetName().isEmpty()) {
1068 aErrorInformation
.sMessage
= OUString( "File ");
1069 aErrorInformation
.sMessage
+= pXMLFile
->GetName();
1070 aErrorInformation
.sMessage
+= OUString( " parsed successfully");
1073 aErrorInformation
.sMessage
= OUString( "XML-File parsed successfully");
1075 if (!XML_Parse(aParser
, reinterpret_cast< char * >(p
), s
, true))
1077 aErrorInformation
.eCode
= XML_GetErrorCode( aParser
);
1078 aErrorInformation
.nLine
= XML_GetErrorLineNumber( aParser
);
1079 aErrorInformation
.nColumn
= XML_GetErrorColumnNumber( aParser
);
1081 aErrorInformation
.sMessage
= OUString( "ERROR: ");
1082 if ( !pXMLFile
->GetName().isEmpty())
1083 aErrorInformation
.sMessage
+= pXMLFile
->GetName();
1085 aErrorInformation
.sMessage
+= OUString( "XML-File (");
1086 aErrorInformation
.sMessage
+= OUString::valueOf(
1087 sal::static_int_cast
< sal_Int64
>(aErrorInformation
.nLine
));
1088 aErrorInformation
.sMessage
+= OUString( ",");
1089 aErrorInformation
.sMessage
+= OUString::valueOf(
1090 sal::static_int_cast
< sal_Int64
>(aErrorInformation
.nColumn
));
1091 aErrorInformation
.sMessage
+= OUString( "): ");
1093 switch (aErrorInformation
.eCode
) {
1094 case XML_ERROR_NO_MEMORY
:
1095 aErrorInformation
.sMessage
+= OUString( "No memory");
1097 case XML_ERROR_SYNTAX
:
1098 aErrorInformation
.sMessage
+= OUString( "Syntax");
1100 case XML_ERROR_NO_ELEMENTS
:
1101 aErrorInformation
.sMessage
+= OUString( "No elements");
1103 case XML_ERROR_INVALID_TOKEN
:
1104 aErrorInformation
.sMessage
+= OUString( "Invalid token");
1106 case XML_ERROR_UNCLOSED_TOKEN
:
1107 aErrorInformation
.sMessage
+= OUString( "Unclosed token");
1109 case XML_ERROR_PARTIAL_CHAR
:
1110 aErrorInformation
.sMessage
+= OUString( "Partial char");
1112 case XML_ERROR_TAG_MISMATCH
:
1113 aErrorInformation
.sMessage
+= OUString( "Tag mismatch");
1115 case XML_ERROR_DUPLICATE_ATTRIBUTE
:
1116 aErrorInformation
.sMessage
+= OUString( "Dublicat attribute");
1118 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT
:
1119 aErrorInformation
.sMessage
+= OUString( "Junk after doc element");
1121 case XML_ERROR_PARAM_ENTITY_REF
:
1122 aErrorInformation
.sMessage
+= OUString( "Param entity ref");
1124 case XML_ERROR_UNDEFINED_ENTITY
:
1125 aErrorInformation
.sMessage
+= OUString( "Undefined entity");
1127 case XML_ERROR_RECURSIVE_ENTITY_REF
:
1128 aErrorInformation
.sMessage
+= OUString( "Recursive entity ref");
1130 case XML_ERROR_ASYNC_ENTITY
:
1131 aErrorInformation
.sMessage
+= OUString( "Async_entity");
1133 case XML_ERROR_BAD_CHAR_REF
:
1134 aErrorInformation
.sMessage
+= OUString( "Bad char ref");
1136 case XML_ERROR_BINARY_ENTITY_REF
:
1137 aErrorInformation
.sMessage
+= OUString( "Binary entity");
1139 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
:
1140 aErrorInformation
.sMessage
+= OUString( "Attribute external entity ref");
1142 case XML_ERROR_MISPLACED_XML_PI
:
1143 aErrorInformation
.sMessage
+= OUString( "Misplaced xml pi");
1145 case XML_ERROR_UNKNOWN_ENCODING
:
1146 aErrorInformation
.sMessage
+= OUString( "Unknown encoding");
1148 case XML_ERROR_INCORRECT_ENCODING
:
1149 aErrorInformation
.sMessage
+= OUString( "Incorrect encoding");
1151 case XML_ERROR_UNCLOSED_CDATA_SECTION
:
1152 aErrorInformation
.sMessage
+= OUString( "Unclosed cdata section");
1154 case XML_ERROR_EXTERNAL_ENTITY_HANDLING
:
1155 aErrorInformation
.sMessage
+= OUString( "External entity handling");
1157 case XML_ERROR_NOT_STANDALONE
:
1158 aErrorInformation
.sMessage
+= OUString( "Not standalone");
1160 case XML_ERROR_NONE
:
1169 osl_unmapMappedFile(h
, p
, s
);
1178 static icu::UnicodeString
lcl_QuotRange(
1179 const icu::UnicodeString
& rString
, const sal_Int32 nStart
,
1180 const sal_Int32 nEnd
, bool bInsideTag
= false )
1182 icu::UnicodeString sReturn
;
1183 assert( nStart
< nEnd
);
1184 assert( nStart
>= 0 );
1185 assert( nEnd
<= rString
.length() );
1186 for (sal_Int32 i
= nStart
; i
< nEnd
; ++i
)
1191 sReturn
.append("<");
1194 sReturn
.append(">");
1198 sReturn
.append(""");
1200 sReturn
.append(rString
[i
]);
1203 if (rString
.startsWith("&", i
, 5))
1204 sReturn
.append('&');
1206 sReturn
.append("&");
1209 sReturn
.append(rString
[i
]);
1216 static bool lcl_isTag( const icu::UnicodeString
& rString
)
1218 static const int nSize
= 13;
1219 static const icu::UnicodeString vTags
[nSize
] = {
1220 "ahelp", "link", "item", "emph", "defaultinline",
1221 "switchinline", "caseinline", "variable",
1222 "bookmark_value", "image", "embedvar", "alt", "sup" };
1224 for( int nIndex
= 0; nIndex
< nSize
; ++nIndex
)
1226 if( rString
.startsWith("<" + vTags
[nIndex
]) ||
1227 rString
== "</" + vTags
[nIndex
] + ">" )
1231 return rString
== "<br/>" || rString
=="<help-id-missing/>";
1234 } /// anonymous namespace
1236 OUString
XMLUtil::QuotHTML( const OUString
&rString
)
1238 if( rString
.trim().isEmpty() )
1240 UErrorCode nIcuErr
= U_ZERO_ERROR
;
1241 static const sal_uInt32 nSearchFlags
=
1242 UREGEX_DOTALL
| UREGEX_CASE_INSENSITIVE
;
1243 static const OUString
sPattern(
1244 "<[/]\?\?[a-z_-]+?(?:| +[a-z]+?=\".*?\") *[/]\?\?>");
1245 static const UnicodeString
sSearchPat(
1246 reinterpret_cast<const UChar
*>(sPattern
.getStr()),
1247 sPattern
.getLength() );
1249 icu::UnicodeString
sSource(
1250 reinterpret_cast<const UChar
*>(
1251 rString
.getStr()), rString
.getLength() );
1253 RegexMatcher
aRegexMatcher( sSearchPat
, nSearchFlags
, nIcuErr
);
1254 aRegexMatcher
.reset( sSource
);
1256 icu::UnicodeString sReturn
;
1257 int32_t nEndPos
= 0;
1258 int32_t nStartPos
= 0;
1259 while( aRegexMatcher
.find(nStartPos
, nIcuErr
) && nIcuErr
== U_ZERO_ERROR
)
1261 nStartPos
= aRegexMatcher
.start(nIcuErr
);
1262 if ( nEndPos
< nStartPos
)
1263 sReturn
.append(lcl_QuotRange(sSource
, nEndPos
, nStartPos
));
1264 nEndPos
= aRegexMatcher
.end(nIcuErr
);
1265 icu::UnicodeString sMatch
= aRegexMatcher
.group(nIcuErr
);
1266 if( lcl_isTag(sMatch
) )
1268 sReturn
.append("<");
1269 sReturn
.append(lcl_QuotRange(sSource
, nStartPos
+1, nEndPos
-1, true));
1270 sReturn
.append(">");
1273 sReturn
.append(lcl_QuotRange(sSource
, nStartPos
, nEndPos
));
1276 if( nEndPos
< sSource
.length() )
1277 sReturn
.append(lcl_QuotRange(sSource
, nEndPos
, sSource
.length()));
1278 sReturn
.append('\0');
1279 return OUString(reinterpret_cast<const sal_Unicode
*>(sReturn
.getBuffer()));
1282 OUString
XMLUtil::UnQuotHTML( const OUString
& rString
)
1284 const OString
sString(OUStringToOString(rString
, RTL_TEXTENCODING_UTF8
));
1285 return OStringToOUString(helper::UnQuotHTML(sString
), RTL_TEXTENCODING_UTF8
);
1288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */