00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #include "KoXmlReader.h"
00063
00064 #ifndef KOXML_USE_QDOM
00065
00066 #include <qxml.h>
00067 #include <qdom.h>
00068
00069 #include <qmap.h>
00070 #include <qcstring.h>
00071
00072
00073 class DQString
00074 {
00075 public:
00076 DQString() { }
00077 DQString( const QString& s1, const QString& s2 ){ str1 = s1; str2 = s2; }
00078 DQString( const DQString& b ) { str1 = b.str1; str2 = b.str2; }
00079 DQString& operator=( const DQString& b ){ str1 = b.str1; str2 = b.str2; return *this; }
00080 bool operator==( const DQString& b ) const { return (str1==b.str1) && (str2==b.str2); }
00081 bool operator!=( const DQString& b ) const { return (str1!=b.str1) || (str2!=b.str2); }
00082 bool operator<( const DQString& b ) const
00083 { return ( str1 < b.str1 ) ? true : ( str1==b.str1 ) ? str2<b.str2 : false; }
00084 QString s1() const { return str1; }
00085 QString s2() const { return str2; }
00086 private:
00087 QString str1, str2;
00088 };
00089
00090
00091 #if 0
00092 DQString b1;
00093 DQString b2;
00094 CHECK( b1==b2, true );
00095 CHECK( b1!=b2, false );
00096
00097 b1 = DQString( "sweet","princess" );
00098 b2 = DQString( "sweet","princess" );
00099 CHECK( b1==b2, true );
00100 CHECK( b1!=b2, false );
00101
00102 b1 = DQString( "sweet","princess" );
00103 b2 = DQString( "bad","prince" );
00104 CHECK( b1==b2, false );
00105 CHECK( b1!=b2, true );
00106 #endif
00107
00108 class KoXmlStream
00109 {
00110 public:
00111 KoXmlStream(){ saveData = true; data.reserve(1024); pos = 0; }
00112 QString stringData() const { return data; }
00113 void setSaveData( bool s ){ saveData = s; }
00114 int at() const { return pos; }
00115 KoXmlStream& operator<<( const QString& str )
00116 { if(saveData) data.append(str); pos+=str.length(); return *this; }
00117 KoXmlStream& appendEscape( const QString& str );
00118
00119 private:
00120 bool saveData;
00121 QString data;
00122 int pos;
00123 };
00124
00125 KoXmlStream& KoXmlStream::appendEscape( const QString& str )
00126 {
00127 unsigned len = str.length();
00128
00129 if( saveData )
00130 {
00131 data.reserve( data.length() + len );
00132 for( unsigned c=0; c<len; c++ )
00133 if( str[c]=='<' ){ data.append( "<"); pos += 4; } else
00134 if( str[c]=='>'){ data.append( ">"); pos+= 4; } else
00135 if( str[c]=='"'){ data.append( """); pos += 6; } else
00136 if( str[c]=='&'){ data.append( "&"); pos += 5; } else
00137 { data.append( str[c] ); pos++; }
00138 }
00139 else
00140 {
00141 pos += len;
00142 for( unsigned c=0; c<len; c++ )
00143 if( str[c]=='<' ) pos += 3; else
00144 if( str[c]=='>') pos+= 3; else
00145 if( str[c]=='"') pos += 5; else
00146 if( str[c]=='&') pos += 4;
00147 }
00148
00149 return *this;
00150 }
00151
00152 class KoXmlNodeData
00153 {
00154 public:
00155
00156 KoXmlNodeData();
00157 virtual ~KoXmlNodeData();
00158
00159
00160 KoXmlNode::NodeType nodeType;
00161 QString tagName;
00162 QString namespaceURI;
00163 QString prefix;
00164 QString localName;
00165
00166
00167 unsigned long count;
00168 void ref() { count++; }
00169 void unref() { --count; if( !count ) delete this; }
00170
00171
00172 virtual const char* typeInfo() const { return "Node"; }
00173 QString nodeName() const;
00174
00175
00176 KoXmlNodeData* parent;
00177 KoXmlNodeData* prev;
00178 KoXmlNodeData* next;
00179 KoXmlNodeData* first;
00180 KoXmlNodeData* last;
00181
00182 QString text();
00183
00184
00185 void appendChild( KoXmlNodeData* child );
00186 virtual void clear();
00187 KoXmlNodeData* ownerDocument();
00188
00189
00190 void setAttribute( const QString& name, const QString& value );
00191 QString attribute( const QString& name );
00192 bool hasAttribute( const QString& name );
00193 void setAttributeNS( const QString& nsURI, const QString& name, const QString& value );
00194 QString attributeNS( const QString& nsURI, const QString& name );
00195 bool hasAttributeNS( const QString& nsURI, const QString& name );
00196
00197
00198 QString data() const;
00199 void setData( const QString& data );
00200
00201
00202 QXmlSimpleReader* xmlReader;
00203 QString buffer;
00204 bool setContent( QXmlInputSource* source, QXmlReader* reader,
00205 QString* errorMsg = 0, int* errorLine = 0, int* errorColumn = 0 );
00206
00207
00208 bool loaded;
00209 unsigned startPos, endPos;
00210 void loadChildren( int depth=1 );
00211 void unloadChildren();
00212 bool fastLoading;
00213
00214 private:
00215 QMap<QString,QString> attr;
00216 QMap<DQString,QString> attrNS;
00217 QString textData;
00218 friend class KoXmlHandler;
00219 };
00220
00221 class KoXmlHandler : public QXmlDefaultHandler
00222 {
00223 public:
00224 KoXmlHandler( KoXmlNodeData*, bool processNamespace );
00225 ~KoXmlHandler();
00226
00227 void setMaxDepth( int d ){ maxDepth = d; }
00228 void setInitialOffset( int ofs ){ parseOffset = ofs; }
00229
00230
00231 bool startDocument();
00232 bool endDocument();
00233
00234 bool startElement( const QString& nsURI, const QString& localName,
00235 const QString& qName, const QXmlAttributes& atts );
00236 bool endElement( const QString& nsURI, const QString& localName,
00237 const QString& qName );
00238
00239 bool characters( const QString& ch );
00240 bool processingInstruction( const QString& target, const QString& data );
00241 bool skippedEntity( const QString& name );
00242
00243
00244 bool startCDATA();
00245 bool endCDATA();
00246 bool startEntity( const QString & );
00247 bool endEntity( const QString & );
00248 bool startDTD( const QString& name, const QString& publicId,
00249 const QString& systemId );
00250 bool comment( const QString& ch );
00251
00252
00253 bool externalEntityDecl( const QString &name, const QString &publicId,
00254 const QString &systemId ) ;
00255
00256
00257 bool notationDecl( const QString & name, const QString & publicId,
00258 const QString & systemId );
00259 bool unparsedEntityDecl( const QString &name, const QString &publicId,
00260 const QString &systemId, const QString ¬ationName ) ;
00261
00262
00263 bool fatalError( const QXmlParseException& exception );
00264
00265 QString errorMsg;
00266 int errorLine;
00267 int errorColumn;
00268
00269 private:
00270 bool processNamespace;
00271 KoXmlNodeData* rootNode;
00272 KoXmlNodeData* currentNode;
00273 QString entityName;
00274 bool cdata;
00275 int parseOffset;
00276 KoXmlStream bufferStream;
00277 int elementDepth;
00278 int maxDepth;
00279 };
00280
00281
00282
00283
00284
00285
00286
00287 KoXmlNodeData::KoXmlNodeData()
00288 {
00289 nodeType = KoXmlNode::NullNode;
00290
00291 tagName = QString::null;
00292 prefix = QString::null;
00293 localName = QString::null;
00294 namespaceURI = QString::null;
00295 textData = QString::null;
00296
00297 count = 1;
00298 parent = 0;
00299 prev = next = 0;
00300 first = last = 0;
00301
00302 xmlReader = 0;
00303 startPos = endPos = 0;
00304
00305 fastLoading = false;
00306
00307
00308
00309 loaded = true;
00310 }
00311
00312 KoXmlNodeData::~KoXmlNodeData()
00313 {
00314 clear();
00315 }
00316
00317 void KoXmlNodeData::clear()
00318 {
00319 if( first )
00320 for( KoXmlNodeData* node = first; node ; )
00321 {
00322 KoXmlNodeData* next = node->next;
00323 node->unref();
00324 node = next;
00325 }
00326
00327 nodeType = KoXmlNode::NullNode;
00328 tagName = QString::null;
00329 prefix = QString::null;
00330 namespaceURI = QString::null;
00331 textData = QString::null;
00332
00333 attr.clear();
00334 attrNS.clear();
00335
00336 parent = 0;
00337 prev = next = 0;
00338 first = last = 0;
00339
00340 delete xmlReader;
00341 xmlReader = 0;
00342 buffer = QString::null;
00343 }
00344
00345 QString KoXmlNodeData::text()
00346 {
00347 QString t( "" );
00348
00349 loadChildren();
00350
00351 KoXmlNodeData* node = first;
00352 while ( node )
00353 {
00354 switch( node->nodeType )
00355 {
00356 case KoXmlNode::ElementNode:
00357 t += node->text(); break;
00358 case KoXmlNode::TextNode:
00359 t += node->data(); break;
00360 case KoXmlNode::CDATASectionNode:
00361 t += node->data(); break;
00362 default: break;
00363 }
00364 node = node->next;
00365 }
00366
00367 return t;
00368 }
00369
00370 QString KoXmlNodeData::nodeName() const
00371 {
00372 QString n;
00373
00374 switch( nodeType )
00375 {
00376 case KoXmlNode::ElementNode:
00377 n = tagName;
00378 if (!prefix.isEmpty()) n.prepend(":").prepend(prefix); break;
00379 case KoXmlNode::TextNode: return QString("#text");
00380 case KoXmlNode::CDATASectionNode: return QString("#cdata-section");
00381 case KoXmlNode::DocumentNode: return QString("#document");
00382 default: break;
00383 }
00384
00385 return n;
00386 }
00387
00388 KoXmlNodeData* KoXmlNodeData::ownerDocument()
00389 {
00390 KoXmlNodeData* owner = this;
00391
00392 while( owner->parent )
00393 owner = owner->parent;
00394
00395 return (owner->nodeType==KoXmlNode::DocumentNode) ? owner : 0;
00396 }
00397
00398 void KoXmlNodeData::appendChild( KoXmlNodeData* node )
00399 {
00400 node->parent = this;
00401 if( !last )
00402 first = last = node;
00403 else
00404 {
00405 last->next = node;
00406 node->prev = last;
00407 node->next = 0;
00408 last = node;
00409 }
00410 }
00411
00412 void KoXmlNodeData::setAttribute( const QString& name, const QString& value )
00413 {
00414 attr[ name ] = value;
00415 }
00416
00417 QString KoXmlNodeData::attribute( const QString& name )
00418 {
00419 return attr[ name ];
00420 }
00421
00422 bool KoXmlNodeData::hasAttribute( const QString& name )
00423 {
00424 return attr.contains( name );
00425 }
00426
00427 void KoXmlNodeData::setAttributeNS( const QString& nsURI,
00428 const QString& name, const QString& value )
00429 {
00430 QString prefix;
00431 QString localName = name;
00432 int i = name.find( ':' );
00433 if( i != -1 )
00434 {
00435 localName = name.mid( i + 1 );
00436 prefix = name.left( i );
00437 }
00438
00439 if( prefix.isNull() ) return;
00440
00441 DQString key( nsURI, localName );
00442 attrNS[ key ] = value;
00443 }
00444
00445 QString KoXmlNodeData::attributeNS( const QString& nsURI, const QString& name )
00446 {
00447 DQString key( nsURI, name );
00448 return attrNS[ key ];
00449 }
00450
00451 bool KoXmlNodeData::hasAttributeNS( const QString& nsURI, const QString& name )
00452 {
00453 DQString key( nsURI, name );
00454 return attrNS.contains( key );
00455 }
00456
00457 QString KoXmlNodeData::data() const
00458 {
00459 return textData;
00460 }
00461
00462 void KoXmlNodeData::setData( const QString& d )
00463 {
00464 textData = d;
00465 }
00466
00467 bool KoXmlNodeData::setContent( QXmlInputSource* source,
00468 QXmlReader* reader, QString* errorMsg, int* errorLine, int* errorColumn )
00469 {
00470 if( nodeType != KoXmlNode::DocumentNode )
00471 return false;
00472
00473 clear();
00474 nodeType = KoXmlNode::DocumentNode;
00475
00476
00477 if( !source ) return false;
00478 if( !reader ) return false;
00479
00480
00481
00482 char* features[] =
00483 {
00484 "http://xml.org/sax/features/namespaces",
00485 "http://xml.org/sax/features/namespace-prefixes",
00486 "http://trolltech.com/xml/features/report-whitespace-only-CharData",
00487 "http://trolltech.com/xml/features/report-start-end-entity"
00488 };
00489 xmlReader = new QXmlSimpleReader;
00490 for( int fi=0; fi<4; fi++ )
00491 xmlReader->setFeature( features[fi], reader->feature( features[fi] ) );
00492
00493 bool processNamespace =
00494 reader->feature( "http://xml.org/sax/features/namespaces" ) &&
00495 !reader->feature( "http://xml.org/sax/features/namespace-prefixes" );
00496
00497 KoXmlHandler handler( this, processNamespace );
00498 reader->setContentHandler( &handler );
00499 reader->setErrorHandler( &handler );
00500 reader->setLexicalHandler( &handler );
00501 reader->setDeclHandler( &handler );
00502 reader->setDTDHandler( &handler );
00503
00504 if( !fastLoading )
00505 handler.setMaxDepth( 4 );
00506
00507 if( !reader->parse( source ) )
00508 {
00509
00510 if( errorMsg ) *errorMsg = handler.errorMsg;
00511 if( errorLine ) *errorLine = handler.errorLine;
00512 if( errorColumn ) *errorColumn = handler.errorColumn;
00513 return false;
00514 }
00515
00516 return true;
00517 }
00518
00519 void KoXmlNodeData::loadChildren( int depth )
00520 {
00521
00522 if( ( depth== 1 ) && loaded ) return;
00523
00524 KoXmlNodeData* doc = ownerDocument();
00525 if( !doc ) return;
00526
00527
00528 if( doc->fastLoading ) return;
00529
00530 unloadChildren();
00531
00532 bool nsProcess =
00533 doc->xmlReader->feature( "http://xml.org/sax/features/namespaces" ) &&
00534 !doc->xmlReader->feature( "http://xml.org/sax/features/namespace-prefixes" );
00535
00536
00537
00538 QString snippet = doc->buffer.mid( startPos, endPos-startPos+1 );
00539
00540
00541 KoXmlHandler handler( this, nsProcess );
00542 handler.setMaxDepth( depth );
00543 handler.setInitialOffset( startPos );
00544 doc->xmlReader->setContentHandler( &handler );
00545 doc->xmlReader->setErrorHandler( &handler );
00546 doc->xmlReader->setLexicalHandler( &handler );
00547 doc->xmlReader->setDeclHandler( &handler );
00548 doc->xmlReader->setDTDHandler( &handler );
00549
00550 QXmlInputSource source;
00551 source.setData( snippet );
00552 if( !doc->xmlReader->parse( source ) )
00553 {
00554
00555
00556 loaded = false;
00557 qWarning( "On-demand loading triggers parse error!" );
00558 }
00559 else
00560 loaded = true;
00561 }
00562
00563 void KoXmlNodeData::unloadChildren()
00564 {
00565 if( !loaded ) return;
00566
00567 if( first )
00568 for( KoXmlNodeData* node = first; node ; )
00569 {
00570 KoXmlNodeData* next = node->next;
00571 node->unloadChildren();
00572 node->unref();
00573 node = next;
00574 }
00575
00576 loaded = false;
00577 first = last = 0;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587 KoXmlHandler::KoXmlHandler( KoXmlNodeData* n, bool ns ):
00588 QXmlDefaultHandler()
00589 {
00590 processNamespace = ns;
00591
00592 rootNode = n;
00593 currentNode = n;
00594 cdata = false;
00595 entityName = QString::null;
00596
00597 errorMsg = QString::null;
00598 errorLine = 0;
00599 errorColumn = 0;
00600
00601 parseOffset = 0;
00602 elementDepth = -1;
00603 maxDepth = 999;
00604
00605 bufferStream.setSaveData( rootNode->nodeType == KoXmlNode::DocumentNode );
00606 }
00607
00608 KoXmlHandler::~KoXmlHandler()
00609 {
00610 }
00611
00612 bool KoXmlHandler::startDocument()
00613 {
00614
00615 currentNode = rootNode;
00616 cdata = false;
00617 entityName = QString::null;
00618 elementDepth = -1;
00619
00620 return true;
00621 }
00622
00623 bool KoXmlHandler::endDocument()
00624 {
00625
00626 if( rootNode->nodeType == KoXmlNode::DocumentNode )
00627 if( currentNode!=rootNode )
00628 return false;
00629
00630 if( rootNode->nodeType == KoXmlNode::DocumentNode )
00631 rootNode->buffer = bufferStream.stringData();
00632
00633 return true;
00634 }
00635
00636 bool KoXmlHandler::startDTD( const QString& name, const QString& publicId,
00637 const QString& systemId )
00638 {
00639 Q_UNUSED( name );
00640 Q_UNUSED( publicId );
00641 Q_UNUSED( systemId );
00642
00643
00644 return true;
00645 }
00646
00647 bool KoXmlHandler::startElement( const QString& nsURI, const QString& localName,
00648 const QString& name, const QXmlAttributes& atts )
00649 {
00650 Q_UNUSED( localName );
00651
00652
00653 if( !currentNode )
00654 return false;
00655
00656
00657 elementDepth++;
00658
00659 QString nodePrefix, nodeLocalName, nodeTagName;
00660 KoXmlNodeData* element = 0;
00661
00662 if( processNamespace )
00663 {
00664
00665 nodeTagName = name;
00666 nodeLocalName = name;
00667 nodePrefix = nsURI.isNull() ? QString::null : QString("");
00668 int i = name.find( ':' );
00669 if( i != -1 )
00670 {
00671 nodeTagName = name.mid( i + 1 );
00672 nodeLocalName = nodeTagName;
00673 nodePrefix = name.left( i );
00674 }
00675
00676 if( elementDepth <= maxDepth )
00677 {
00678
00679 element = new KoXmlNodeData;
00680 element->nodeType = KoXmlNode::ElementNode;
00681 element->parent = currentNode;
00682 element->namespaceURI = nsURI;
00683 element->prefix = nodePrefix;
00684 element->localName = nodeLocalName;
00685 element->tagName = nodeTagName;
00686
00687
00688 element->endPos = element->startPos = parseOffset + bufferStream.at();
00689
00690
00691 for( int c=0; c<atts.length(); c++ )
00692 {
00693 QString prefix;
00694 QString qName;
00695 QString name;
00696
00697 name = qName = atts.qName(c);
00698 int i = qName.find( ':' );
00699 if( i != -1 ) prefix = qName.left( i );
00700 if( i != -1 ) name = qName.mid( i + 1 );
00701 element->setAttributeNS( atts.uri(c), qName, atts.value(c) );
00702 element->setAttribute( name, atts.value(c) );
00703 }
00704 }
00705
00706
00707 if( ( rootNode->nodeType != KoXmlNode::DocumentNode ) || !rootNode->fastLoading )
00708 {
00709 bufferStream << "<";
00710 if( !nodePrefix.isEmpty() )
00711 bufferStream << nodePrefix << ":";
00712 bufferStream << localName;
00713 bufferStream << " xmlns";
00714 if( !nodePrefix.isEmpty() )
00715 bufferStream << ":" << nodePrefix;
00716 bufferStream << "=\"";
00717 bufferStream.appendEscape( nsURI );
00718 bufferStream << "\"";
00719 for( int c=0; c<atts.length(); c++ )
00720 {
00721 QString prefix;
00722 QString name = atts.qName(c);
00723 int i = name.find( ':' );
00724 if( i != -1 ) prefix = name.left( i );
00725 if( i != -1 ) name = atts.qName(c).mid( i + 1 );
00726 if( !atts.uri(c).isEmpty() )
00727 bufferStream << " xmlns:" << prefix << "=\"" << atts.uri(c) << "\"";
00728 bufferStream << " ";
00729 if( !prefix.isEmpty() ) bufferStream << prefix << ":";
00730 bufferStream << name << "=\"";
00731 bufferStream.appendEscape( atts.value(c) );
00732 bufferStream << "\"";
00733 }
00734 bufferStream << ">";
00735 }
00736 }
00737 else
00738 {
00739
00740 nodeTagName = name;
00741
00742 if( elementDepth <= maxDepth )
00743 {
00744
00745 element = new KoXmlNodeData;
00746 element->nodeType = KoXmlNode::ElementNode;
00747 element->parent = currentNode;
00748 element->namespaceURI = QString::null;
00749 element->prefix = QString::null;
00750 element->localName = QString::null;
00751 element->tagName = nodeTagName;
00752
00753 if( rootNode->nodeType == KoXmlNode::DocumentNode )
00754 element->fastLoading = rootNode->fastLoading;
00755
00756
00757 element->endPos = element->startPos = parseOffset + bufferStream.at();
00758
00759
00760 for( int c=0; c<atts.length(); c++ )
00761 element->setAttribute( atts.qName(c), atts.value(c) );
00762 }
00763
00764
00765 if( ( rootNode->nodeType != KoXmlNode::DocumentNode ) || !rootNode->fastLoading )
00766 {
00767 bufferStream << "<";
00768 bufferStream << nodeTagName;
00769 for( int c=0; c<atts.length(); c++ )
00770 {
00771 bufferStream << " " << atts.qName(c) << "=\"";
00772 bufferStream.appendEscape( atts.value(c) );
00773 bufferStream << "\"";
00774 }
00775 bufferStream << ">";
00776 }
00777
00778 }
00779
00780
00781
00782
00783
00784
00785 if( elementDepth == 0 )
00786 if( rootNode->nodeType != KoXmlNode::DocumentNode )
00787 {
00788 delete element;
00789 return true;
00790 }
00791
00792 if( element )
00793 {
00794
00795 currentNode->loaded = true;
00796 currentNode->appendChild( element );
00797 currentNode = element;
00798 }
00799 else
00800 currentNode->loaded = false;
00801
00802 return true;
00803 }
00804
00805 bool KoXmlHandler::endElement( const QString& nsURI, const QString& localName,
00806 const QString& qName )
00807 {
00808 Q_UNUSED( nsURI );
00809 Q_UNUSED( localName );
00810
00811
00812 if( !currentNode ) return false;
00813 if( !currentNode->parent ) return false;
00814
00815
00816 if( rootNode->nodeType == KoXmlNode::DocumentNode )
00817 if( currentNode == rootNode )
00818 return false;
00819
00820
00821 if( ( rootNode->nodeType != KoXmlNode::DocumentNode ) || !rootNode->fastLoading )
00822 bufferStream << "</" << qName << ">";
00823
00824
00825 currentNode->endPos = parseOffset + bufferStream.at() - 1;
00826
00827
00828 if( elementDepth <= maxDepth )
00829 currentNode = currentNode->parent;
00830
00831
00832 elementDepth--;
00833
00834 return true;
00835 }
00836
00837 bool KoXmlHandler::characters( const QString& str )
00838 {
00839
00840 if( rootNode->nodeType == KoXmlNode::DocumentNode )
00841 if( currentNode == rootNode )
00842 return false;
00843
00844
00845 if( !entityName.isEmpty() )
00846 {
00847
00848
00849 return true;
00850 }
00851
00852 if( cdata )
00853 {
00854
00855 if( elementDepth <= maxDepth )
00856 {
00857 KoXmlNodeData* cdata = new KoXmlNodeData;
00858 cdata->nodeType = KoXmlNode::CDATASectionNode;
00859 cdata->parent = currentNode;
00860 cdata->setData( str );
00861 currentNode->appendChild( cdata );
00862 }
00863
00864 if( ( rootNode->nodeType != KoXmlNode::DocumentNode ) || !rootNode->fastLoading )
00865 bufferStream << "<![CDATA[" << str << "]]>";
00866 }
00867 else
00868 {
00869
00870 if( elementDepth <= maxDepth )
00871 {
00872 KoXmlNodeData* text = new KoXmlNodeData;
00873 text->nodeType = KoXmlNode::TextNode;
00874 text->parent = currentNode;
00875 text->setData( str );
00876 currentNode->appendChild( text );
00877 }
00878
00879
00880 if( ( rootNode->nodeType != KoXmlNode::DocumentNode ) || !rootNode->fastLoading )
00881 bufferStream.appendEscape( str );
00882 }
00883
00884 return true;
00885 }
00886
00887 bool KoXmlHandler::processingInstruction( const QString& target,
00888 const QString& data )
00889 {
00890
00891 if( !currentNode )
00892 return false;
00893
00894 KoXmlNodeData* instruction = new KoXmlNodeData;
00895 instruction->nodeType = KoXmlNode::ProcessingInstructionNode;
00896 instruction->parent = currentNode;
00897 instruction->tagName = target;
00898 instruction->setData( data );
00899
00900 currentNode->appendChild( instruction );
00901
00902 return true;
00903 }
00904
00905 bool KoXmlHandler::skippedEntity( const QString& name )
00906 {
00907 Q_UNUSED( name );
00908
00909
00910 return true;
00911 }
00912
00913 bool KoXmlHandler::startCDATA()
00914 {
00915 cdata = true;
00916 return true;
00917 }
00918
00919 bool KoXmlHandler::endCDATA()
00920 {
00921 cdata = false;
00922 return true;
00923 }
00924
00925 bool KoXmlHandler::startEntity( const QString& name )
00926 {
00927 entityName = name;
00928 return true;
00929 }
00930
00931 bool KoXmlHandler::endEntity( const QString& name )
00932 {
00933 Q_UNUSED( name );
00934 entityName = QString::null;
00935 return true;
00936 }
00937
00938 bool KoXmlHandler::comment( const QString& comment )
00939 {
00940 Q_UNUSED( comment );
00941
00942
00943 return true;
00944 }
00945
00946 bool KoXmlHandler::unparsedEntityDecl( const QString &name,
00947 const QString &publicId, const QString &systemId, const QString ¬ationName )
00948 {
00949 Q_UNUSED( name );
00950 Q_UNUSED( publicId );
00951 Q_UNUSED( systemId );
00952 Q_UNUSED( notationName );
00953
00954
00955 return true;
00956 }
00957
00958 bool KoXmlHandler::externalEntityDecl( const QString &name,
00959 const QString &publicId, const QString &systemId )
00960 {
00961 Q_UNUSED( name );
00962 Q_UNUSED( publicId );
00963 Q_UNUSED( systemId );
00964
00965
00966 return true;
00967 }
00968
00969 bool KoXmlHandler::notationDecl( const QString & name,
00970 const QString & publicId, const QString & systemId )
00971 {
00972 Q_UNUSED( name );
00973 Q_UNUSED( publicId );
00974 Q_UNUSED( systemId );
00975
00976
00977 return true;
00978 }
00979
00980 bool KoXmlHandler::fatalError( const QXmlParseException& exception )
00981 {
00982 errorMsg = exception.message();
00983 errorLine = exception.lineNumber();
00984 errorColumn = exception.columnNumber();
00985 return QXmlDefaultHandler::fatalError( exception );
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995 KoXmlNode::KoXmlNode()
00996 {
00997 d = new KoXmlNodeData;
00998 }
00999
01000
01001 KoXmlNode::~KoXmlNode()
01002 {
01003 if( d ) d->unref();
01004 }
01005
01006
01007 KoXmlNode::KoXmlNode( const KoXmlNode& node )
01008 {
01009 d = node.d;
01010 d->ref();
01011 }
01012
01013
01014 KoXmlNode::KoXmlNode( KoXmlNodeData* data )
01015 {
01016 d = data;
01017 data->ref();
01018 }
01019
01020
01021 KoXmlNode& KoXmlNode::operator=( const KoXmlNode& node )
01022 {
01023 d->unref();
01024 d = node.d;
01025 d->ref();
01026 return *this;
01027 }
01028
01029
01030 bool KoXmlNode::operator==( const KoXmlNode& node ) const
01031 {
01032 if( isNull() && node.isNull() ) return true;
01033 return( d==node.d );
01034 }
01035
01036
01037 bool KoXmlNode::operator!=( const KoXmlNode& node ) const
01038 {
01039 if( isNull() && !node.isNull() ) return true;
01040 if( !isNull() && node.isNull() ) return true;
01041 if( isNull() && node.isNull() ) return false;
01042 return( d!=node.d );
01043 }
01044
01045 KoXmlNode::NodeType KoXmlNode::nodeType() const
01046 {
01047 return d->nodeType;
01048 }
01049
01050 bool KoXmlNode::isElement() const
01051 {
01052 return d->nodeType == ElementNode;
01053 }
01054
01055 bool KoXmlNode::isText() const
01056 {
01057 return (d->nodeType == TextNode) || isCDATASection();
01058 }
01059
01060 bool KoXmlNode::isCDATASection() const
01061 {
01062 return d->nodeType == CDATASectionNode;
01063 }
01064
01065 bool KoXmlNode::isDocument() const
01066 {
01067 return d->nodeType == DocumentNode;
01068 }
01069
01070 bool KoXmlNode::isNull() const
01071 {
01072 return d->nodeType == NullNode;
01073 }
01074
01075 void KoXmlNode::clear()
01076 {
01077 d->unref();
01078 d = new KoXmlNodeData;
01079 }
01080
01081 QString KoXmlNode::nodeName() const
01082 {
01083 return d->nodeName();
01084 }
01085
01086 QString KoXmlNode::prefix() const
01087 {
01088 return isElement() ? d->prefix : QString::null;
01089 }
01090
01091 QString KoXmlNode::namespaceURI() const
01092 {
01093 return isElement() ? d->namespaceURI : QString::null;
01094 }
01095
01096 QString KoXmlNode::localName() const
01097 {
01098 return isElement() ? d->localName : QString::null;
01099 }
01100
01101 KoXmlDocument KoXmlNode::ownerDocument() const
01102 {
01103 KoXmlNodeData* node = d;
01104 while( node->parent ) node = node->parent;
01105
01106 if( node->nodeType != DocumentNode ) return KoXmlDocument();
01107 return KoXmlDocument( node );
01108 }
01109
01110 KoXmlNode KoXmlNode::parentNode() const
01111 {
01112 return d->parent ? KoXmlNode( d->parent ) : KoXmlNode();
01113 }
01114
01115 bool KoXmlNode::hasChildNodes() const
01116 {
01117 d->loadChildren();
01118 return d->first!=0 ;
01119 }
01120
01121 KoXmlNode KoXmlNode::firstChild() const
01122 {
01123 if( !d->fastLoading )
01124 d->loadChildren();
01125 return d->first ? KoXmlNode( d->first ) : KoXmlNode();
01126 }
01127
01128 KoXmlNode KoXmlNode::lastChild() const
01129 {
01130 if( !d->fastLoading )
01131 d->loadChildren();
01132 return d->last ? KoXmlNode( d->last ) : KoXmlNode();
01133 }
01134
01135 KoXmlNode KoXmlNode::nextSibling() const
01136 {
01137 return d->next ? KoXmlNode( d->next ) : KoXmlNode();
01138 }
01139
01140 KoXmlNode KoXmlNode::previousSibling() const
01141 {
01142 return d->prev ? KoXmlNode( d->prev ) : KoXmlNode();
01143 }
01144
01145 KoXmlNode KoXmlNode::namedItem( const QString& name ) const
01146 {
01147 if( !d->fastLoading )
01148 d->loadChildren();
01149
01150 KoXmlNodeData* node = d->first;
01151 while ( node )
01152 {
01153 if( node->nodeName() == name )
01154 return KoXmlNode( node );
01155 node = node->next;
01156 }
01157
01158
01159 return KoXmlNode();
01160 }
01161
01162 KoXmlNode KoXmlNode::namedItemNS( const QString& nsURI, const QString& name ) const
01163 {
01164 if( !d->fastLoading )
01165 d->loadChildren();
01166
01167 KoXmlNodeData* node = d->first;
01168 while ( node )
01169 {
01170 if( !node->prefix.isNull() )
01171 if( node->namespaceURI == nsURI )
01172 if( node->localName == name )
01173 return KoXmlNode( node );
01174 node = node->next;
01175 }
01176
01177
01178 return KoXmlNode();
01179 }
01180
01181 KoXmlElement KoXmlNode::toElement()
01182 {
01183 return isElement() ? KoXmlElement( d ) : KoXmlElement();
01184 }
01185
01186 KoXmlText KoXmlNode::toText()
01187 {
01188 return isText() ? KoXmlText( d ) : KoXmlText();
01189 }
01190
01191 KoXmlCDATASection KoXmlNode::toCDATASection()
01192 {
01193 return isCDATASection() ? KoXmlCDATASection( (KoXmlNodeData*)d ) :
01194 KoXmlCDATASection();
01195 }
01196
01197 KoXmlDocument KoXmlNode::toDocument()
01198 {
01199 return isDocument() ? KoXmlDocument( d ) : KoXmlDocument();
01200 }
01201
01202 void KoXmlNode::load( int depth )
01203 {
01204 d->loadChildren( depth );
01205 }
01206
01207 void KoXmlNode::unload()
01208 {
01209 d->unloadChildren();
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219 KoXmlElement::KoXmlElement(): KoXmlNode()
01220 {
01221 d->unref();
01222 d = new KoXmlNodeData;
01223 }
01224
01225 KoXmlElement::~KoXmlElement()
01226 {
01227 d->unref();
01228 d = 0;
01229 }
01230
01231
01232 KoXmlElement::KoXmlElement( const KoXmlElement& element ): KoXmlNode()
01233 {
01234 d->unref();
01235 d = element.d;
01236 d->ref();
01237 }
01238
01239 KoXmlElement::KoXmlElement( KoXmlNodeData* data ): KoXmlNode()
01240 {
01241 d->unref();
01242 d = data;
01243 d->ref();
01244 }
01245
01246
01247 KoXmlElement& KoXmlElement::operator=( const KoXmlElement& element )
01248 {
01249 KoXmlNode::operator=( element );
01250 return *this;
01251 }
01252
01253 bool KoXmlElement::operator== ( const KoXmlElement& element ) const
01254 {
01255 if( isNull() || element.isNull() ) return false;
01256 return (d==element.d);
01257 }
01258
01259 bool KoXmlElement::operator!= ( const KoXmlElement& element ) const
01260 {
01261 if( isNull() && element.isNull() ) return false;
01262 if( isNull() || element.isNull() ) return true;
01263 return (d!=element.d);
01264 }
01265
01266 QString KoXmlElement::tagName() const
01267 {
01268 return isElement() ? ((KoXmlNodeData*)d)->tagName: QString::null;
01269 }
01270
01271 QString KoXmlElement::text() const
01272 {
01273 return d->text();
01274 }
01275
01276 bool KoXmlElement::isElement() const
01277 {
01278 return true;
01279 }
01280
01281 QString KoXmlElement::attribute( const QString& name ) const
01282 {
01283 return attribute( name, QString::null );
01284 }
01285
01286 QString KoXmlElement::attribute( const QString& name,
01287 const QString& defaultValue ) const
01288 {
01289 if( !isElement() )
01290 return defaultValue;
01291
01292 if( !hasAttribute( name ) )
01293 return defaultValue;
01294
01295 return ((KoXmlNodeData*)d)->attribute( name );
01296 }
01297
01298 QString KoXmlElement::attributeNS( const QString& namespaceURI,
01299 const QString& localName, const QString& defaultValue ) const
01300 {
01301 if( !isElement() )
01302 return defaultValue;
01303
01304 if( !hasAttributeNS( namespaceURI,localName ) )
01305 return defaultValue;
01306
01307 return ((KoXmlNodeData*)d)->attributeNS( namespaceURI,localName );
01308 }
01309
01310 bool KoXmlElement::hasAttribute( const QString& name ) const
01311 {
01312 return isElement() ? ((KoXmlNodeData*)d)->hasAttribute( name ) : false;
01313 }
01314
01315 bool KoXmlElement::hasAttributeNS( const QString& namespaceURI,
01316 const QString& localName ) const
01317 {
01318 return isElement() ? ((KoXmlNodeData*)d)->hasAttributeNS(
01319 namespaceURI, localName ) : false;;
01320 }
01321
01322
01323
01324
01325
01326
01327
01328 KoXmlText::KoXmlText(): KoXmlNode()
01329 {
01330 d->unref();
01331 d = new KoXmlNodeData;
01332 d->nodeType = TextNode;
01333 }
01334
01335 KoXmlText::~KoXmlText()
01336 {
01337 if( d ) d->unref();
01338 d = 0;
01339 }
01340
01341 KoXmlText::KoXmlText( const KoXmlText& text ): KoXmlNode()
01342 {
01343 d->unref();
01344 d = (KoXmlNodeData*) text.d;
01345 d->ref();
01346 }
01347
01348 KoXmlText::KoXmlText( KoXmlNodeData* data ): KoXmlNode()
01349 {
01350 d->unref();
01351 d = data;
01352 d->ref();
01353 }
01354
01355 bool KoXmlText::isText() const
01356 {
01357 return true;
01358 }
01359
01360 QString KoXmlText::data() const
01361 {
01362 return ((KoXmlNodeData*)d)->data();
01363 }
01364
01365 KoXmlText& KoXmlText::operator=( const KoXmlText& element )
01366 {
01367 KoXmlNode::operator=( element );
01368 return *this;
01369 }
01370
01371
01372
01373
01374
01375
01376
01377 KoXmlCDATASection::KoXmlCDATASection(): KoXmlText()
01378 {
01379 d->unref();
01380 d = new KoXmlNodeData;
01381 d->nodeType = KoXmlNode::CDATASectionNode;
01382 }
01383
01384 KoXmlCDATASection::~KoXmlCDATASection()
01385 {
01386 d->unref();
01387 d = 0;
01388 }
01389
01390 KoXmlCDATASection::KoXmlCDATASection( const KoXmlCDATASection& cdata ):
01391 KoXmlText()
01392 {
01393 d->unref();
01394 d = (KoXmlNodeData*) cdata.d;
01395 d->ref();
01396 }
01397
01398 KoXmlCDATASection::KoXmlCDATASection( KoXmlNodeData* cdata ):
01399 KoXmlText()
01400 {
01401 d->unref();
01402 d = cdata;
01403 d->ref();
01404 }
01405
01406 bool KoXmlCDATASection::isCDATASection() const
01407 {
01408 return true;
01409 }
01410
01411 KoXmlCDATASection& KoXmlCDATASection::operator=( const KoXmlCDATASection& cdata )
01412 {
01413 KoXmlNode::operator=( cdata );
01414 return *this;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423 KoXmlDocument::KoXmlDocument(): KoXmlNode()
01424 {
01425 d->unref();
01426 d = new KoXmlNodeData;
01427 d->nodeType = KoXmlNode::DocumentNode;
01428 }
01429
01430 KoXmlDocument::~KoXmlDocument()
01431 {
01432 d->unref();
01433 d = 0;
01434 }
01435
01436 KoXmlDocument::KoXmlDocument( KoXmlNodeData* data ): KoXmlNode()
01437 {
01438 d->unref();
01439 d = data;
01440 d->ref();
01441 }
01442
01443
01444 KoXmlDocument::KoXmlDocument( const KoXmlDocument& doc ): KoXmlNode()
01445 {
01446 d->unref();
01447 d = doc.d;
01448 d->ref();
01449 }
01450
01451
01452 KoXmlDocument& KoXmlDocument::operator=( const KoXmlDocument& doc )
01453 {
01454 KoXmlNode::operator=( doc );
01455 return *this;
01456 }
01457
01458
01459 bool KoXmlDocument::operator==( const KoXmlDocument& doc ) const
01460 {
01461 return( d==doc.d );
01462 }
01463
01464
01465 bool KoXmlDocument::operator!=( const KoXmlDocument& doc ) const
01466 {
01467 return( d!=doc.d );
01468 }
01469
01470 bool KoXmlDocument::isDocument() const
01471 {
01472 return true;
01473 }
01474
01475 KoXmlElement KoXmlDocument::documentElement() const
01476 {
01477 for( KoXmlNodeData* node=d->first; node; )
01478 if( node->nodeType==KoXmlNode::ElementNode )
01479 return KoXmlElement( node );
01480 else node = node->next;
01481
01482 return KoXmlElement();
01483 }
01484
01485 void KoXmlDocument::setFastLoading( bool f )
01486 {
01487 d->fastLoading = f;
01488 }
01489
01490 bool KoXmlDocument::fastLoading() const
01491 {
01492 return d->fastLoading;
01493 }
01494
01495 bool KoXmlDocument::setContent( QXmlInputSource *source, QXmlReader *reader,
01496 QString* errorMsg, int* errorLine, int* errorColumn )
01497 {
01498 if( d->nodeType != KoXmlNode::DocumentNode )
01499 return false;
01500
01501 return d->setContent( source, reader, errorMsg, errorLine, errorColumn );
01502 }
01503
01504
01505 bool KoXmlDocument::setContent( QIODevice* device, QString* errorMsg,
01506 int* errorLine, int* errorColumn )
01507 {
01508 return setContent( device, false, errorMsg, errorLine, errorColumn );
01509 }
01510
01511 bool KoXmlDocument::setContent( QIODevice* device, bool namespaceProcessing,
01512 QString* errorMsg, int* errorLine, int* errorColumn )
01513 {
01514 if( d->nodeType != KoXmlNode::DocumentNode )
01515 return false;
01516
01517 QXmlSimpleReader reader;
01518 reader.setFeature( "http://xml.org/sax/features/namespaces", namespaceProcessing );
01519 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", !namespaceProcessing );
01520 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
01521
01522
01523
01524
01525 QXmlInputSource source( device );
01526 return d->setContent( &source, &reader, errorMsg, errorLine, errorColumn );
01527 }
01528
01529 #endif
01530
01531 KoXmlElement KoXml::namedItemNS( const KoXmlNode& node, const char* nsURI,
01532 const char* localName )
01533 {
01534 #ifdef KOXML_USE_QDOM
01535
01536 KoXmlNode n = node.firstChild();
01537 for ( ; !n.isNull(); n = n.nextSibling() ) {
01538 if ( n.isElement() && n.localName() == localName &&
01539 n.namespaceURI() == nsURI )
01540 return n.toElement();
01541 }
01542 return KoXmlElement();
01543 #else
01544 return node.namedItemNS( nsURI, localName).toElement();
01545 #endif
01546 }
01547
01548 void KoXml::load( KoXmlNode& node, int depth )
01549 {
01550 #ifdef KOXML_USE_QDOM
01551
01552 Q_UNUSED( node );
01553 Q_UNUSED( depth );
01554 #else
01555 node.load( depth );
01556 #endif
01557 }
01558
01559
01560 void KoXml::unload( KoXmlNode& node )
01561 {
01562 #ifdef KOXML_USE_QDOM
01563
01564 Q_UNUSED( node );
01565 #else
01566 node.unload();
01567 #endif
01568 }