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 #include <QTextCodec>
00065 #include <QTextDecoder>
00066
00067 #ifndef KOXML_USE_QDOM
00068
00069 #include <qxml.h>
00070 #include <qdom.h>
00071
00072 #include <QBuffer>
00073 #include <QHash>
00074 #include <QPair>
00075 #include <QStringList>
00076 #include <QVector>
00077
00078
00079
00080
00081
00082
00083
00084 #define KOXML_COMPACT
00085
00086
00087 typedef QPair<QString,QString> KoXmlStringPair;
00088
00089
00090
00091 inline uint qHash( const KoXmlStringPair &p )
00092 {
00093 return qHash(p.first[0].unicode()) ^ 0x1477;
00094
00095
00096
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106 class KoXmlPackedItem
00107 {
00108 public:
00109 bool attr:1;
00110 KoXmlNode::NodeType type:3;
00111
00112 #ifdef KOXML_COMPACT
00113 quint32 childStart:28;
00114 #else
00115 unsigned depth:28;
00116 #endif
00117
00118 unsigned nameIndex;
00119 unsigned nsURIIndex;
00120 QString value;
00121
00122
00123
00124 #if 0
00125 KoXmlPackedItem(): attr(false), type(KoXmlNode::NullNode), depth(0) {}
00126 #endif
00127 };
00128
00129
00130
00131
00132
00133
00134
00135 typedef QVector<KoXmlPackedItem> KoXmlPackedGroup;
00136
00137
00138 #define GROUP_GROW_SHIFT 3
00139 #define GROUP_GROW_SIZE (1 << GROUP_GROW_SHIFT)
00140
00141 class KoXmlPackedDocument
00142 {
00143 public:
00144 bool processNamespace;
00145 #ifdef KOXML_COMPACT
00146
00147 QHash<int, KoXmlPackedGroup> groups;
00148 #else
00149 QVector<KoXmlPackedItem> items;
00150 #endif
00151
00152 QStringList stringList;
00153
00154 private:
00155 QHash<QString, unsigned> stringHash;
00156
00157 unsigned cacheString( const QString& str )
00158 {
00159 if( str.isEmpty() )
00160 return 0;
00161
00162 const unsigned& ii = stringHash[str];
00163 if(ii > 0)
00164 return ii;
00165
00166
00167 unsigned i = stringList.count();
00168 stringList.append( str );
00169 stringHash.insert( str, i );
00170
00171 return i;
00172 }
00173
00174 QHash<QString, unsigned> valueHash;
00175 QStringList valueList;
00176
00177 QString cacheValue( const QString& value )
00178 {
00179 if( value.isEmpty() )
00180 return 0;
00181
00182 const unsigned& ii = valueHash[value];
00183 if(ii > 0)
00184 return valueList[ii];
00185
00186
00187 unsigned i = valueList.count();
00188 valueList.append( value );
00189 valueHash.insert( value, i );
00190
00191 return valueList[i];
00192 }
00193
00194 #ifdef KOXML_COMPACT
00195 public:
00196 KoXmlPackedItem& itemAt( unsigned depth, unsigned index )
00197 {
00198 KoXmlPackedGroup& group = groups[depth];
00199 return group[index];
00200 }
00201
00202 unsigned itemCount( unsigned depth )
00203 {
00204 const KoXmlPackedGroup& group = groups[depth];
00205 return group.count();
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 unsigned currentDepth;
00220
00221 KoXmlPackedItem& newItem( unsigned depth )
00222 {
00223 KoXmlPackedGroup& group = groups[depth];
00224
00225
00226 if( (groups.size() % GROUP_GROW_SIZE) == 0 )
00227 group.reserve( GROUP_GROW_SIZE * (1+(groups.size() >> GROUP_GROW_SHIFT)) );
00228 group.resize( group.count()+1 );
00229
00230
00231
00232 KoXmlPackedItem& item = group[group.count()-1];
00233 item.attr = false;
00234 item.type = KoXmlNode::NullNode;
00235 item.nameIndex = 0;
00236 item.nsURIIndex = 0;
00237 item.childStart = itemCount( depth + 1);
00238
00239 return item;
00240 }
00241
00242 void clear()
00243 {
00244 currentDepth = 0;
00245 stringHash.clear();
00246 stringList.clear();
00247 valueHash.clear();
00248 valueList.clear();
00249 groups.clear();
00250
00251
00252 cacheString(QString());
00253
00254
00255 KoXmlPackedItem& rootItem = newItem(0);
00256 rootItem.type = KoXmlNode::DocumentNode;
00257 }
00258
00259 void finish()
00260 {
00261
00262 stringHash.clear();
00263 valueHash.clear();
00264 valueList.clear();
00265
00266
00267 for(int d = 0; d < groups.count(); d++)
00268 {
00269 KoXmlPackedGroup& group = groups[d];
00270 group.squeeze();
00271 }
00272 }
00273
00274
00275 void addElement( const QString& name, const QString& nsURI )
00276 {
00277 KoXmlPackedItem& item = newItem(currentDepth+1);
00278 item.type = KoXmlNode::ElementNode;
00279 item.nameIndex = cacheString(name);
00280 item.nsURIIndex = cacheString(nsURI);
00281
00282 currentDepth++;
00283 }
00284
00285 void closeElement()
00286 {
00287 currentDepth--;
00288 }
00289
00290 void addAttribute( const QString& name, const QString& nsURI, const QString& value )
00291 {
00292 KoXmlPackedItem& item = newItem(currentDepth+1);
00293 item.attr = true;
00294 item.nameIndex = cacheString(name);
00295 item.nsURIIndex = cacheString(nsURI);
00296
00297 item.value = value;
00298 }
00299
00300 void addText( const QString& text )
00301 {
00302 KoXmlPackedItem& item = newItem(currentDepth+1);
00303 item.type = KoXmlNode::TextNode;
00304 item.value = text;
00305 }
00306
00307 void addCData( const QString& text )
00308 {
00309 KoXmlPackedItem& item = newItem(currentDepth+1);
00310 item.type = KoXmlNode::CDATASectionNode;
00311 item.value = text;
00312 }
00313
00314 void addProcessingInstruction()
00315 {
00316 KoXmlPackedItem& item = newItem(currentDepth+1);
00317 item.type = KoXmlNode::ProcessingInstructionNode;
00318 }
00319
00320 public:
00321 KoXmlPackedDocument(): processNamespace(false), currentDepth(0)
00322 {
00323 clear();
00324 }
00325
00326 #else
00327
00328 private:
00329 unsigned elementDepth;
00330
00331 public:
00332
00333 KoXmlPackedItem& newItem()
00334 {
00335 unsigned count = items.count() + 512;
00336 count = 1024 * (count >> 10);
00337 items.reserve(count);
00338
00339 items.resize( items.count() + 1 );
00340
00341
00342
00343 KoXmlPackedItem& item = items[items.count()-1];
00344 item.attr = false;
00345 item.type = KoXmlNode::NullNode;
00346 item.nameIndex = 0;
00347 item.nsURIIndex = 0;
00348 item.depth = 0;
00349
00350 return item;
00351 }
00352
00353 void addElement( const QString& name, const QString& nsURI )
00354 {
00355
00356 elementDepth++;
00357
00358 KoXmlPackedItem& item = newItem();
00359
00360 item.attr = false;
00361 item.type = KoXmlNode::ElementNode;
00362 item.depth = elementDepth;
00363 item.nameIndex = cacheString( name );
00364 item.nsURIIndex = cacheString( nsURI );
00365 }
00366
00367 void closeElement()
00368 {
00369
00370 elementDepth--;
00371 }
00372
00373 void addAttribute( const QString& name, const QString& nsURI, const QString& value )
00374 {
00375 KoXmlPackedItem& item = newItem();
00376
00377 item.attr = true;
00378 item.type = KoXmlNode::NullNode;
00379 item.depth = elementDepth;
00380 item.nameIndex = cacheString( name );
00381 item.nsURIIndex = cacheString( nsURI );
00382
00383 item.value = value;
00384 }
00385
00386 void addText( const QString& str )
00387 {
00388 KoXmlPackedItem& item = newItem();
00389
00390 item.attr = false;
00391 item.type = KoXmlNode::TextNode;
00392 item.depth = elementDepth + 1;
00393 item.nameIndex = 0;
00394 item.nsURIIndex = 0;
00395 item.value = str;
00396 }
00397
00398 void addCData( const QString& str )
00399 {
00400 KoXmlPackedItem& item = newItem();
00401
00402 item.attr = false;
00403 item.type = KoXmlNode::CDATASectionNode;
00404 item.depth = elementDepth + 1;
00405 item.nameIndex = 0;
00406 item.nsURIIndex = 0;
00407 item.value = str;
00408 }
00409
00410 void addProcessingInstruction()
00411 {
00412 KoXmlPackedItem& item = newItem();
00413
00414 item.attr = false;
00415 item.type = KoXmlNode::ProcessingInstructionNode;
00416 item.depth = elementDepth + 1;
00417 item.nameIndex = 0;
00418 item.nsURIIndex = 0;
00419 item.value.clear();
00420 }
00421
00422 void clear()
00423 {
00424 stringList.clear();
00425 stringHash.clear();
00426 valueHash.clear();
00427 valueList.clear();
00428 items.clear();
00429 elementDepth = 0;
00430
00431
00432 cacheString( "." );
00433
00434 KoXmlPackedItem& rootItem = newItem();
00435 rootItem.attr = false;
00436 rootItem.type = KoXmlNode::DocumentNode;
00437 rootItem.depth = 0;
00438 rootItem.nsURIIndex = 0;
00439 rootItem.nameIndex = 0;
00440 }
00441
00442 void finish()
00443 {
00444 stringHash.clear();
00445 valueList.clear();
00446 valueHash.clear();
00447 items.squeeze();
00448 }
00449
00450 KoXmlPackedDocument(): processNamespace(false), elementDepth(0)
00451 {
00452 }
00453
00454 #endif
00455
00456 };
00457
00458
00459
00460
00461
00462
00463
00464 class KoXmlHandler : public QXmlDefaultHandler
00465 {
00466 public:
00467 KoXmlHandler( KoXmlPackedDocument* doc );
00468 ~KoXmlHandler();
00469
00470
00471 bool startDocument();
00472 bool endDocument();
00473
00474 bool startElement( const QString& nsURI, const QString& localName,
00475 const QString& qName, const QXmlAttributes& atts );
00476 bool endElement( const QString& nsURI, const QString& localName,
00477 const QString& qName );
00478
00479 bool characters( const QString& ch );
00480 bool processingInstruction( const QString& target, const QString& data );
00481 bool skippedEntity( const QString& name );
00482
00483
00484 bool startCDATA();
00485 bool endCDATA();
00486 bool startEntity( const QString & );
00487 bool endEntity( const QString & );
00488 bool startDTD( const QString& name, const QString& publicId,
00489 const QString& systemId );
00490 bool comment( const QString& ch );
00491
00492
00493 bool externalEntityDecl( const QString &name, const QString &publicId,
00494 const QString &systemId ) ;
00495
00496
00497 bool notationDecl( const QString & name, const QString & publicId,
00498 const QString & systemId );
00499 bool unparsedEntityDecl( const QString &name, const QString &publicId,
00500 const QString &systemId, const QString ¬ationName ) ;
00501
00502
00503 bool fatalError( const QXmlParseException& exception );
00504
00505 QString errorMsg;
00506 int errorLine;
00507 int errorColumn;
00508
00509 private:
00510 bool processNamespace;
00511 QString entityName;
00512 bool cdata;
00513
00514 KoXmlPackedDocument* document;
00515 };
00516
00517
00518 KoXmlHandler::KoXmlHandler( KoXmlPackedDocument* doc ):
00519 QXmlDefaultHandler()
00520 {
00521 document = doc;
00522 processNamespace = doc->processNamespace;
00523
00524 cdata = false;
00525 entityName = QString();
00526
00527 errorMsg = QString();
00528 errorLine = 0;
00529 errorColumn = 0;
00530 }
00531
00532 KoXmlHandler::~KoXmlHandler()
00533 {
00534 }
00535
00536
00537 bool KoXmlHandler::startDocument()
00538 {
00539
00540 cdata = false;
00541 entityName = QString();
00542
00543 errorMsg = QString();
00544 errorLine = 0;
00545 errorColumn = 0;
00546
00547 document->clear();
00548 return true;
00549 }
00550
00551 bool KoXmlHandler::endDocument()
00552 {
00553 document->finish();
00554 return true;
00555 }
00556
00557 bool KoXmlHandler::startDTD( const QString& name, const QString& publicId,
00558 const QString& systemId )
00559 {
00560 Q_UNUSED( name );
00561 Q_UNUSED( publicId );
00562 Q_UNUSED( systemId );
00563
00564
00565 return true;
00566 }
00567
00568 bool KoXmlHandler::startElement( const QString& nsURI, const QString& localName,
00569 const QString& name, const QXmlAttributes& atts )
00570 {
00571 Q_UNUSED( localName );
00572
00573 document->addElement( name, nsURI );
00574
00575
00576 for( int c=0; c<atts.length(); c++ )
00577 document->addAttribute( atts.qName(c), atts.uri(c), atts.value(c) );
00578
00579 return true;
00580 }
00581
00582 bool KoXmlHandler::endElement( const QString& nsURI, const QString& localName,
00583 const QString& qName )
00584 {
00585 Q_UNUSED( nsURI );
00586 Q_UNUSED( localName );
00587 Q_UNUSED( qName );
00588
00589 document->closeElement();
00590
00591 return true;
00592 }
00593
00594 bool KoXmlHandler::characters( const QString& str )
00595 {
00596
00597 if( !entityName.isEmpty() )
00598 {
00599
00600
00601 return true;
00602 }
00603
00604
00605 if( cdata )
00606 document->addCData( str );
00607 else
00608 document->addText( str );
00609
00610 return true;
00611 }
00612
00613 bool KoXmlHandler::processingInstruction( const QString& target,
00614 const QString& data )
00615 {
00616 Q_UNUSED( target );
00617 Q_UNUSED( data );
00618
00619 document->addProcessingInstruction();
00620
00621 return true;
00622 }
00623
00624 bool KoXmlHandler::skippedEntity( const QString& name )
00625 {
00626 Q_UNUSED( name );
00627
00628
00629 return true;
00630 }
00631
00632 bool KoXmlHandler::startCDATA()
00633 {
00634 cdata = true;
00635 return true;
00636 }
00637
00638 bool KoXmlHandler::endCDATA()
00639 {
00640 cdata = false;
00641 return true;
00642 }
00643
00644 bool KoXmlHandler::startEntity( const QString& name )
00645 {
00646 entityName = name;
00647 return true;
00648 }
00649
00650 bool KoXmlHandler::endEntity( const QString& name )
00651 {
00652 Q_UNUSED( name );
00653 entityName.clear();
00654 return true;
00655 }
00656
00657 bool KoXmlHandler::comment( const QString& comment )
00658 {
00659 Q_UNUSED( comment );
00660
00661
00662 return true;
00663 }
00664
00665 bool KoXmlHandler::unparsedEntityDecl( const QString &name,
00666 const QString &publicId, const QString &systemId, const QString ¬ationName )
00667 {
00668 Q_UNUSED( name );
00669 Q_UNUSED( publicId );
00670 Q_UNUSED( systemId );
00671 Q_UNUSED( notationName );
00672
00673
00674 return true;
00675 }
00676
00677 bool KoXmlHandler::externalEntityDecl( const QString &name,
00678 const QString &publicId, const QString &systemId )
00679 {
00680 Q_UNUSED( name );
00681 Q_UNUSED( publicId );
00682 Q_UNUSED( systemId );
00683
00684
00685 return true;
00686 }
00687
00688 bool KoXmlHandler::notationDecl( const QString & name,
00689 const QString & publicId, const QString & systemId )
00690 {
00691 Q_UNUSED( name );
00692 Q_UNUSED( publicId );
00693 Q_UNUSED( systemId );
00694
00695
00696 return true;
00697 }
00698
00699 bool KoXmlHandler::fatalError( const QXmlParseException& exception )
00700 {
00701 errorMsg = exception.message();
00702 errorLine = exception.lineNumber();
00703 errorColumn = exception.columnNumber();
00704 return QXmlDefaultHandler::fatalError( exception );
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 class KoXmlNodeData
00715 {
00716 public:
00717
00718 KoXmlNodeData();
00719 ~KoXmlNodeData();
00720
00721 #ifdef KOXML_COMPACT
00722 unsigned nodeDepth;
00723 #endif
00724
00725
00726 KoXmlNode::NodeType nodeType;
00727 QString tagName;
00728 QString namespaceURI;
00729 QString prefix;
00730 QString localName;
00731
00732
00733 unsigned long count;
00734 void ref() { count++; }
00735 void unref() { if( this == &null) return; if( !--count ) delete this; }
00736
00737
00738 bool emptyDocument;
00739 QString nodeName() const;
00740
00741
00742 KoXmlNodeData* parent;
00743 KoXmlNodeData* prev;
00744 KoXmlNodeData* next;
00745 KoXmlNodeData* first;
00746 KoXmlNodeData* last;
00747
00748 QString text();
00749
00750
00751 void appendChild( KoXmlNodeData* child );
00752 void clear();
00753
00754
00755 inline void setAttribute( const QString& name, const QString& value );
00756 inline QString attribute( const QString& name, const QString& def ) const;
00757 inline bool hasAttribute( const QString& name ) const;
00758 inline void setAttributeNS( const QString& nsURI, const QString& name, const QString& value );
00759 inline QString attributeNS( const QString& nsURI, const QString& name, const QString& def ) const;
00760 inline bool hasAttributeNS( const QString& nsURI, const QString& name ) const;
00761 inline void clearAttributes();
00762
00763
00764 QString data() const;
00765 void setData( const QString& data );
00766
00767
00768 KoXmlPackedDocument* packedDoc;
00769 unsigned long nodeIndex;
00770
00771
00772 bool setContent( QXmlInputSource* source, QXmlReader* reader,
00773 QString* errorMsg = 0, int* errorLine = 0, int* errorColumn = 0 );
00774 bool setContent( QXmlInputSource* source, bool namespaceProcessing,
00775 QString* errorMsg = 0, int* errorLine = 0, int* errorColumn = 0 );
00776
00777
00778 bool loaded;
00779 void loadChildren( int depth=1 );
00780 void unloadChildren();
00781
00782 void dump();
00783
00784 static KoXmlNodeData null;
00785
00786
00787 QDomNode asQDomNode( QDomDocument ownerDoc ) const;
00788
00789 private:
00790 QHash<QString,QString> attr;
00791 QHash<KoXmlStringPair,QString> attrNS;
00792 QString textData;
00793 friend class KoXmlHandler;
00794 friend class KoXmlElement;
00795 };
00796
00797 KoXmlNodeData KoXmlNodeData::null;
00798
00799 KoXmlNodeData::KoXmlNodeData()
00800 {
00801 #ifdef KOXML_COMPACT
00802 nodeDepth = 0;
00803 #endif
00804 nodeType = KoXmlNode::NullNode;
00805
00806 tagName = QString();
00807 prefix = QString();
00808 localName = QString();
00809 namespaceURI = QString();
00810 textData = QString();
00811
00812 count = 1;
00813 parent = 0;
00814 prev = next = 0;
00815 first = last = 0;
00816
00817 packedDoc = 0;
00818 nodeIndex = 0;
00819
00820 emptyDocument = true;
00821
00822 loaded = false;
00823 }
00824
00825 KoXmlNodeData::~KoXmlNodeData()
00826 {
00827 clear();
00828 }
00829
00830 void KoXmlNodeData::clear()
00831 {
00832 if( first )
00833 for( KoXmlNodeData* node = first; node ; )
00834 {
00835 KoXmlNodeData* next = node->next;
00836 node->unref();
00837 node = next;
00838 }
00839
00840
00841
00842 if(nodeType == KoXmlNode::DocumentNode)
00843 delete packedDoc;
00844
00845 nodeType = KoXmlNode::NullNode;
00846 tagName.clear();
00847 prefix.clear();
00848 namespaceURI.clear();
00849 textData.clear();
00850 packedDoc = 0;
00851
00852 attr.clear();
00853 attrNS.clear();
00854
00855 parent = 0;
00856 prev = next = 0;
00857 first = last = 0;
00858
00859 loaded = false;
00860 }
00861
00862 QString KoXmlNodeData::text()
00863 {
00864 QString t;
00865
00866 loadChildren();
00867
00868 KoXmlNodeData* node = first;
00869 while ( node )
00870 {
00871 switch( node->nodeType )
00872 {
00873 case KoXmlNode::ElementNode:
00874 t += node->text(); break;
00875 case KoXmlNode::TextNode:
00876 t += node->data(); break;
00877 case KoXmlNode::CDATASectionNode:
00878 t += node->data(); break;
00879 default: break;
00880 }
00881 node = node->next;
00882 }
00883
00884 return t;
00885 }
00886
00887 QString KoXmlNodeData::nodeName() const
00888 {
00889 QString n;
00890
00891 switch( nodeType )
00892 {
00893 case KoXmlNode::ElementNode:
00894 n = tagName;
00895 if (!prefix.isEmpty()) n.prepend(':').prepend(prefix); break;
00896 case KoXmlNode::TextNode: return QLatin1String("#text");
00897 case KoXmlNode::CDATASectionNode: return QLatin1String("#cdata-section");
00898 case KoXmlNode::DocumentNode: return QLatin1String("#document");
00899 default: break;
00900 }
00901
00902 return n;
00903 }
00904
00905 void KoXmlNodeData::appendChild( KoXmlNodeData* node )
00906 {
00907 node->parent = this;
00908 if( !last )
00909 first = last = node;
00910 else
00911 {
00912 last->next = node;
00913 node->prev = last;
00914 node->next = 0;
00915 last = node;
00916 }
00917 }
00918
00919 void KoXmlNodeData::setAttribute( const QString& name, const QString& value )
00920 {
00921 attr[ name ] = value;
00922 }
00923
00924 QString KoXmlNodeData::attribute( const QString& name, const QString& def ) const
00925 {
00926 if( attr.contains(name) )
00927 return attr[ name ];
00928 else
00929 return def;
00930 }
00931
00932 bool KoXmlNodeData::hasAttribute( const QString& name ) const
00933 {
00934 return attr.contains( name );
00935 }
00936
00937 void KoXmlNodeData::setAttributeNS( const QString& nsURI,
00938 const QString& name, const QString& value )
00939 {
00940 QString prefix;
00941 QString localName = name;
00942 int i = name.indexOf( ':' );
00943 if( i != -1 )
00944 {
00945 localName = name.mid( i + 1 );
00946 prefix = name.left( i );
00947 }
00948
00949 if( prefix.isNull() ) return;
00950
00951 KoXmlStringPair key( nsURI, localName );
00952 attrNS[ key ] = value;
00953 }
00954
00955 QString KoXmlNodeData::attributeNS( const QString& nsURI, const QString& name,
00956 const QString& def ) const
00957 {
00958 KoXmlStringPair key( nsURI, name );
00959 if( attrNS.contains( key ) )
00960 return attrNS[ key ];
00961 else
00962 return def;
00963 }
00964
00965 bool KoXmlNodeData::hasAttributeNS( const QString& nsURI, const QString& name ) const
00966 {
00967 KoXmlStringPair key( nsURI, name );
00968 return attrNS.contains( key );
00969 }
00970
00971 void KoXmlNodeData::clearAttributes()
00972 {
00973 attr.clear();
00974 attrNS.clear();
00975 }
00976
00977 QString KoXmlNodeData::data() const
00978 {
00979 return textData;
00980 }
00981
00982 void KoXmlNodeData::setData( const QString& d )
00983 {
00984 textData = d;
00985 }
00986
00987 bool KoXmlNodeData::setContent( QXmlInputSource* source, bool namespaceProcessing,
00988 QString* errorMsg, int* errorLine, int* errorColumn )
00989 {
00990 QXmlSimpleReader reader;
00991 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), namespaceProcessing);
00992 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), !namespaceProcessing);
00993 reader.setFeature(QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData"), false);
00994
00995 return setContent(source, &reader, errorMsg, errorLine, errorColumn);
00996 }
00997
00998 bool KoXmlNodeData::setContent( QXmlInputSource* source,
00999 QXmlReader* reader, QString* errorMsg, int* errorLine, int* errorColumn )
01000 {
01001 if( nodeType != KoXmlNode::DocumentNode )
01002 return false;
01003
01004 clear();
01005 nodeType = KoXmlNode::DocumentNode;
01006
01007
01008 if( !source ) return false;
01009 if( !reader ) return false;
01010
01011 delete packedDoc;
01012 packedDoc = new KoXmlPackedDocument;
01013 packedDoc->processNamespace = false;
01014
01015 packedDoc->processNamespace =
01016 reader->feature( "http://xml.org/sax/features/namespaces" ) &&
01017 !reader->feature( "http://xml.org/sax/features/namespace-prefixes" );
01018
01019 KoXmlHandler handler( packedDoc );
01020 reader->setContentHandler( &handler );
01021 reader->setErrorHandler( &handler );
01022 reader->setLexicalHandler( &handler );
01023 reader->setDeclHandler( &handler );
01024 reader->setDTDHandler( &handler );
01025
01026 bool result = reader->parse(source);
01027 if( !result )
01028 {
01029
01030 if( errorMsg ) *errorMsg = handler.errorMsg;
01031 if( errorLine ) *errorLine = handler.errorLine;
01032 if( errorColumn ) *errorColumn = handler.errorColumn;
01033 return false;
01034 }
01035
01036
01037
01038 loadChildren();
01039
01040 return true;
01041 }
01042
01043 #ifdef KOXML_COMPACT
01044
01045 void KoXmlNodeData::loadChildren( int depth )
01046 {
01047
01048 if( !packedDoc ) return;
01049
01050
01051 if( loaded && (depth<=1) ) return;
01052
01053
01054 unloadChildren();
01055
01056
01057 KoXmlNodeData* lastDat = 0;
01058 const KoXmlPackedItem& self = packedDoc->itemAt( nodeDepth, nodeIndex );
01059
01060 unsigned childStop = 0;
01061 if( nodeIndex == packedDoc->itemCount(nodeDepth)-1 )
01062 childStop = packedDoc->itemCount(nodeDepth+1);
01063 else
01064 {
01065 const KoXmlPackedItem& next = packedDoc->itemAt( nodeDepth, nodeIndex+1 );
01066 childStop = next.childStart;
01067 }
01068
01069 for(unsigned i = self.childStart; i < childStop; i++ )
01070 {
01071 const KoXmlPackedItem& item = packedDoc->itemAt( nodeDepth + 1, i );
01072 bool textItem = (item.type==KoXmlNode::TextNode);
01073 textItem |= (item.type==KoXmlNode::CDATASectionNode);
01074
01075
01076 if(item.attr)
01077 {
01078 QString name = packedDoc->stringList[item.nameIndex];
01079 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01080 QString value = item.value;
01081
01082 QString prefix;
01083
01084 QString qName;
01085 QString localName;
01086
01087 localName = qName = name;
01088 int i = qName.indexOf( ':' );
01089 if( i != -1 ) prefix = qName.left( i );
01090 if( i != -1 ) localName = qName.mid( i + 1 );
01091
01092 if(packedDoc->processNamespace)
01093 {
01094 setAttributeNS(nsURI, qName, value);
01095 setAttribute(localName, value);
01096 }
01097 else
01098 setAttribute( qName, value );
01099 }
01100 else
01101 {
01102 QString name = packedDoc->stringList[item.nameIndex];
01103 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01104 QString value = item.value;
01105
01106 QString nodeName = name;
01107 QString localName;
01108 QString prefix;
01109
01110 if(packedDoc->processNamespace)
01111 {
01112 localName = name;
01113 int di = name.indexOf( ':' );
01114 if( di != -1 )
01115 {
01116 localName = name.mid( di + 1 );
01117 prefix = name.left( di );
01118 }
01119 nodeName = localName;
01120 }
01121
01122
01123 KoXmlNodeData* dat = new KoXmlNodeData;
01124 dat->nodeIndex = i;
01125 dat->packedDoc = packedDoc;
01126 dat->nodeDepth = nodeDepth + 1;
01127 dat->nodeType = item.type;
01128 dat->tagName = nodeName;
01129 dat->localName = localName;
01130 dat->prefix = prefix;
01131 dat->namespaceURI = nsURI;
01132 dat->count = 1;
01133 dat->parent = this;
01134 dat->prev = lastDat;
01135 dat->next = 0;
01136 dat->first = 0;
01137 dat->last = 0;
01138 dat->loaded = false;
01139 dat->textData = (textItem) ? value : QString();
01140
01141
01142 first = (first) ? first : dat;
01143 last = dat;
01144 if(lastDat)
01145 lastDat->next = dat;
01146 lastDat = dat;
01147
01148
01149 if(depth > 1)
01150 dat->loadChildren(depth - 1);
01151 }
01152 }
01153
01154 loaded = true;
01155 }
01156
01157 #else
01158
01159 void KoXmlNodeData::loadChildren( int depth )
01160 {
01161
01162 if( !packedDoc ) return;
01163
01164
01165 if( loaded && (depth<=1) ) return;
01166
01167
01168 unloadChildren();
01169
01170 KoXmlNodeData* lastDat = 0;
01171 int nodeDepth = packedDoc->items[nodeIndex].depth;
01172
01173 for(int i = nodeIndex + 1; i < packedDoc->items.count(); i++ )
01174 {
01175 KoXmlPackedItem& item = packedDoc->items[i];
01176 bool textItem = (item.type==KoXmlNode::TextNode);
01177 textItem |= (item.type==KoXmlNode::CDATASectionNode);
01178
01179
01180 if(!item.attr && (item.type == KoXmlNode::ElementNode))
01181 if(item.depth <= (unsigned)nodeDepth)
01182 break;
01183
01184
01185 if(item.attr && (item.depth == (unsigned)nodeDepth))
01186 {
01187 QString name = packedDoc->stringList[item.nameIndex];
01188 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01189 QString value = item.value;
01190
01191 QString prefix;
01192
01193 QString qName;
01194 QString localName;
01195
01196 localName = qName = name;
01197 int i = qName.indexOf( ':' );
01198 if( i != -1 ) prefix = qName.left( i );
01199 if( i != -1 ) localName = qName.mid( i + 1 );
01200
01201 if(packedDoc->processNamespace)
01202 {
01203 setAttributeNS(nsURI, qName, value);
01204 setAttribute(localName, value);
01205 }
01206 else
01207 setAttribute( name, value );
01208 }
01209
01210
01211 if(!item.attr)
01212 {
01213 bool instruction = (item.type == KoXmlNode::ProcessingInstructionNode);
01214 bool ok = (textItem||instruction) ? (item.depth==(unsigned)nodeDepth) : (item.depth==(unsigned)nodeDepth+1);
01215
01216 ok = (item.depth==(unsigned)nodeDepth+1);
01217
01218 if(ok)
01219 {
01220 QString name = packedDoc->stringList[item.nameIndex];
01221 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01222 QString value = item.value;
01223
01224 QString nodeName = name;
01225 QString localName;
01226 QString prefix;
01227
01228 if(packedDoc->processNamespace)
01229 {
01230 localName = name;
01231 int di = name.indexOf( ':' );
01232 if( di != -1 )
01233 {
01234 localName = name.mid( di + 1 );
01235 prefix = name.left( di );
01236 }
01237 nodeName = localName;
01238 }
01239
01240
01241 KoXmlNodeData* dat = new KoXmlNodeData;
01242 dat->nodeIndex = i;
01243 dat->packedDoc = packedDoc;
01244 dat->nodeType = item.type;
01245 dat->tagName = nodeName;
01246 dat->localName = localName;
01247 dat->prefix = prefix;
01248 dat->namespaceURI = nsURI;
01249 dat->count = 1;
01250 dat->parent = this;
01251 dat->prev = lastDat;
01252 dat->next = 0;
01253 dat->first = 0;
01254 dat->last = 0;
01255 dat->loaded = false;
01256 dat->textData = (textItem) ? value : QString();
01257
01258
01259 first = (first) ? first : dat;
01260 last = dat;
01261 if(lastDat)
01262 lastDat->next = dat;
01263 lastDat = dat;
01264
01265
01266 if(depth > 1)
01267 dat->loadChildren(depth - 1);
01268 }
01269 }
01270 }
01271
01272 loaded = true;
01273 }
01274 #endif
01275
01276 void KoXmlNodeData::unloadChildren()
01277 {
01278
01279 if( !packedDoc ) return;
01280
01281 if( !loaded ) return;
01282
01283 if( first )
01284 for( KoXmlNodeData* node = first; node ; )
01285 {
01286 KoXmlNodeData* next = node->next;
01287 node->unloadChildren();
01288 node->unref();
01289 node = next;
01290 }
01291
01292 clearAttributes();
01293 loaded = false;
01294 first = last = 0;
01295 }
01296
01297 #ifdef KOXML_COMPACT
01298
01299
01300 static QDomNode itemAsQDomNode( QDomDocument ownerDoc, KoXmlPackedDocument* packedDoc,
01301 unsigned nodeDepth, unsigned nodeIndex )
01302 {
01303
01304 if( !packedDoc )
01305 return QDomNode();
01306
01307 const KoXmlPackedItem& self = packedDoc->itemAt( nodeDepth, nodeIndex );
01308
01309 unsigned childStop = 0;
01310 if( nodeIndex == packedDoc->itemCount(nodeDepth)-1 )
01311 childStop = packedDoc->itemCount(nodeDepth+1);
01312 else
01313 {
01314 const KoXmlPackedItem& next = packedDoc->itemAt( nodeDepth, nodeIndex+1 );
01315 childStop = next.childStart;
01316 }
01317
01318
01319 if( self.type == KoXmlNode::NullNode )
01320 return QDomNode();
01321
01322
01323 if( self.type == KoXmlNode::ElementNode )
01324 {
01325 QDomElement element;
01326
01327 QString name = packedDoc->stringList[self.nameIndex];
01328 QString nsURI = packedDoc->stringList[self.nsURIIndex];
01329
01330 if( packedDoc->processNamespace )
01331 element = ownerDoc.createElementNS( nsURI, name );
01332 else
01333 element = ownerDoc.createElement( name );
01334
01335
01336 for(unsigned i = self.childStart; i < childStop; i++ )
01337 {
01338 const KoXmlPackedItem& item = packedDoc->itemAt( nodeDepth+1, i );
01339 bool textItem = (item.type==KoXmlNode::TextNode);
01340 textItem |= (item.type==KoXmlNode::CDATASectionNode);
01341
01342
01343 if(item.attr)
01344 {
01345 QString name = packedDoc->stringList[item.nameIndex];
01346 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01347 QString value = item.value;
01348
01349 QString prefix;
01350
01351 QString qName;
01352 QString localName;
01353
01354 localName = qName = name;
01355 int i = qName.indexOf( ':' );
01356 if( i != -1 ) prefix = qName.left( i );
01357 if( i != -1 ) localName = qName.mid( i + 1 );
01358
01359 if(packedDoc->processNamespace)
01360 {
01361 element.setAttributeNS(nsURI, qName, value);
01362 element.setAttribute(localName, value);
01363 }
01364 else
01365 element.setAttribute( name, value );
01366 }
01367 else
01368 {
01369
01370 QDomNode childNode = itemAsQDomNode( ownerDoc, packedDoc, nodeDepth+1, i );
01371 element.appendChild( childNode );
01372 }
01373 }
01374
01375 return element;
01376 }
01377
01378
01379 if( self.type == KoXmlNode::TextNode )
01380 {
01381 QString text = self.value;
01382
01383
01384 QDomText textNode = ownerDoc.createTextNode( text );
01385 return textNode;
01386 }
01387
01388
01389 return QDomNode();
01390 }
01391
01392 QDomNode KoXmlNodeData::asQDomNode( QDomDocument ownerDoc ) const
01393 {
01394 return itemAsQDomNode( ownerDoc, packedDoc, nodeDepth, nodeIndex );
01395 }
01396
01397 #else
01398
01399 static QDomNode itemAsQDomNode( QDomDocument ownerDoc, KoXmlPackedDocument* packedDoc,
01400 unsigned nodeIndex )
01401 {
01402
01403 if( !packedDoc )
01404 return QDomNode();
01405
01406 KoXmlPackedItem& item = packedDoc->items[nodeIndex];
01407
01408
01409 if( item.type == KoXmlNode::NullNode )
01410 return QDomNode();
01411
01412
01413 if( item.type == KoXmlNode::ElementNode )
01414 {
01415 QDomElement element;
01416
01417 QString name = packedDoc->stringList[item.nameIndex];
01418 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01419
01420 if( packedDoc->processNamespace )
01421 element = ownerDoc.createElementNS( nsURI, name );
01422 else
01423 element = ownerDoc.createElement( name );
01424
01425
01426 int nodeDepth = item.depth;
01427 for(int i = nodeIndex + 1; i < packedDoc->items.count(); i++ )
01428 {
01429 KoXmlPackedItem& item = packedDoc->items[i];
01430 bool textItem = (item.type==KoXmlNode::TextNode);
01431 textItem |= (item.type==KoXmlNode::CDATASectionNode);
01432
01433
01434 if(!item.attr && (item.type == KoXmlNode::ElementNode))
01435 if(item.depth <= (unsigned)nodeDepth)
01436 break;
01437
01438
01439 if(item.attr && (item.depth == (unsigned)nodeDepth))
01440 {
01441 QString name = packedDoc->stringList[item.nameIndex];
01442 QString nsURI = packedDoc->stringList[item.nsURIIndex];
01443 QString value = item.value;
01444 QString prefix;
01445
01446 QString qName;
01447 QString localName;
01448
01449 localName = qName = name;
01450 int i = qName.indexOf( ':' );
01451 if( i != -1 ) prefix = qName.left( i );
01452 if( i != -1 ) localName = qName.mid( i + 1 );
01453
01454 if(packedDoc->processNamespace)
01455 {
01456 element.setAttributeNS(nsURI, qName, value);
01457 element.setAttribute(localName, value);
01458 }
01459 else
01460 element.setAttribute( name, value );
01461 }
01462
01463
01464 if( !item.attr && (item.depth == (unsigned)nodeDepth+1) )
01465 {
01466
01467 QDomNode childNode = itemAsQDomNode( ownerDoc, packedDoc, i );
01468 element.appendChild( childNode );
01469 }
01470 }
01471
01472 return element;
01473 }
01474
01475
01476 if( item.type == KoXmlNode::TextNode )
01477 {
01478 QString text = item.value;
01479
01480 QDomText textNode = ownerDoc.createTextNode( text );
01481 return textNode;
01482 }
01483
01484
01485 return QDomNode();
01486 }
01487
01488 QDomNode KoXmlNodeData::asQDomNode( QDomDocument ownerDoc ) const
01489 {
01490 return itemAsQDomNode( ownerDoc, packedDoc, nodeIndex );
01491 }
01492
01493 #endif
01494
01495 void KoXmlNodeData::dump()
01496 {
01497 printf("NodeData %p\n", this);
01498
01499 printf(" nodeIndex: %d\n", (int)nodeIndex);
01500 printf(" packedDoc: %p\n", packedDoc);
01501
01502 printf(" nodeType : %d\n", (int)nodeType);
01503 printf(" tagName: %s\n", qPrintable( tagName ) );
01504 printf(" namespaceURI: %s\n", qPrintable( namespaceURI ) );
01505 printf(" prefix: %s\n", qPrintable( prefix ) );
01506 printf(" localName: %s\n", qPrintable( localName ) );
01507
01508 printf(" parent : %p\n", parent);
01509 printf(" prev : %p\n", prev);
01510 printf(" next : %p\n", next);
01511 printf(" first : %p\n", first);
01512 printf(" last : %p\n", last);
01513
01514 printf(" count: %ld\n", count);
01515
01516 if(loaded)
01517 printf(" loaded: TRUE\n");
01518 else
01519 printf(" loaded: FALSE\n");
01520 }
01521
01522
01523
01524
01525
01526
01527
01528
01529 KoXmlNode::KoXmlNode()
01530 {
01531 d = &KoXmlNodeData::null;
01532 }
01533
01534
01535 KoXmlNode::~KoXmlNode()
01536 {
01537 if( d )
01538 if( d != &KoXmlNodeData::null )
01539 d->unref();
01540
01541 d = 0;
01542 }
01543
01544
01545 KoXmlNode::KoXmlNode( const KoXmlNode& node )
01546 {
01547 d = node.d;
01548 d->ref();
01549 }
01550
01551
01552 KoXmlNode::KoXmlNode( KoXmlNodeData* data )
01553 {
01554 d = data;
01555 data->ref();
01556 }
01557
01558
01559 KoXmlNode& KoXmlNode::operator=( const KoXmlNode& node )
01560 {
01561 d->unref();
01562 d = node.d;
01563 d->ref();
01564 return *this;
01565 }
01566
01567
01568 bool KoXmlNode::operator==( const KoXmlNode& node ) const
01569 {
01570 if( isNull() && node.isNull() ) return true;
01571 return( d==node.d );
01572 }
01573
01574
01575 bool KoXmlNode::operator!=( const KoXmlNode& node ) const
01576 {
01577 if( isNull() && !node.isNull() ) return true;
01578 if( !isNull() && node.isNull() ) return true;
01579 if( isNull() && node.isNull() ) return false;
01580 return( d!=node.d );
01581 }
01582
01583 KoXmlNode::NodeType KoXmlNode::nodeType() const
01584 {
01585 return d->nodeType;
01586 }
01587
01588 bool KoXmlNode::isNull() const
01589 {
01590 return d->nodeType == NullNode;
01591 }
01592
01593 bool KoXmlNode::isElement() const
01594 {
01595 return d->nodeType == ElementNode;
01596 }
01597
01598 bool KoXmlNode::isText() const
01599 {
01600 return (d->nodeType == TextNode) || isCDATASection();
01601 }
01602
01603 bool KoXmlNode::isCDATASection() const
01604 {
01605 return d->nodeType == CDATASectionNode;
01606 }
01607
01608 bool KoXmlNode::isDocument() const
01609 {
01610 return d->nodeType == DocumentNode;
01611 }
01612
01613 void KoXmlNode::clear()
01614 {
01615 d->unref();
01616 d = new KoXmlNodeData;
01617 }
01618
01619 QString KoXmlNode::nodeName() const
01620 {
01621 return d->nodeName();
01622 }
01623
01624 QString KoXmlNode::prefix() const
01625 {
01626 return isElement() ? d->prefix : QString();
01627 }
01628
01629 QString KoXmlNode::namespaceURI() const
01630 {
01631 return isElement() ? d->namespaceURI : QString();
01632 }
01633
01634 QString KoXmlNode::localName() const
01635 {
01636 return isElement() ? d->localName : QString();
01637 }
01638
01639 KoXmlDocument KoXmlNode::ownerDocument() const
01640 {
01641 KoXmlNodeData* node = d;
01642 while( node->parent ) node = node->parent;
01643
01644 return KoXmlDocument( node );
01645 }
01646
01647 KoXmlNode KoXmlNode::parentNode() const
01648 {
01649 return d->parent ? KoXmlNode( d->parent ) : KoXmlNode();
01650 }
01651
01652 bool KoXmlNode::hasChildNodes() const
01653 {
01654 if( isText() )
01655 return false;
01656
01657 if( !d->loaded)
01658 d->loadChildren();
01659
01660 return d->first!=0 ;
01661 }
01662
01663 int KoXmlNode::childNodesCount() const
01664 {
01665 if( isText() )
01666 return 0;
01667
01668 if( !d->loaded)
01669 d->loadChildren();
01670
01671 KoXmlNodeData* node = d->first;
01672 int count = 0;
01673 while ( node )
01674 {
01675 count++;
01676 node = node->next;
01677 }
01678
01679 return count;
01680 }
01681
01682 KoXmlNode KoXmlNode::firstChild() const
01683 {
01684 if( !d->loaded)
01685 d->loadChildren();
01686 return d->first ? KoXmlNode( d->first ) : KoXmlNode();
01687 }
01688
01689 KoXmlNode KoXmlNode::lastChild() const
01690 {
01691 if( !d->loaded)
01692 d->loadChildren();
01693 return d->last ? KoXmlNode( d->last ) : KoXmlNode();
01694 }
01695
01696 KoXmlNode KoXmlNode::nextSibling() const
01697 {
01698 return d->next ? KoXmlNode( d->next ) : KoXmlNode();
01699 }
01700
01701 KoXmlNode KoXmlNode::previousSibling() const
01702 {
01703 return d->prev ? KoXmlNode( d->prev ) : KoXmlNode();
01704 }
01705
01706 KoXmlNode KoXmlNode::namedItem( const QString& name ) const
01707 {
01708 if( !d->loaded)
01709 d->loadChildren();
01710
01711 KoXmlNodeData* node = d->first;
01712 while ( node )
01713 {
01714 if( node->nodeName() == name )
01715 return KoXmlNode( node );
01716 node = node->next;
01717 }
01718
01719
01720 return KoXmlNode();
01721 }
01722
01723 KoXmlNode KoXmlNode::namedItemNS( const QString& nsURI, const QString& name ) const
01724 {
01725 if( !d->loaded)
01726 d->loadChildren();
01727
01728
01729 KoXmlNodeData* node = d->first;
01730 while ( node )
01731 {
01732 if( !node->prefix.isNull() )
01733 if( node->namespaceURI == nsURI )
01734 if( node->localName == name )
01735 return KoXmlNode( node );
01736 node = node->next;
01737 }
01738
01739
01740 return KoXmlNode();
01741 }
01742
01743 KoXmlElement KoXmlNode::toElement() const
01744 {
01745 return isElement() ? KoXmlElement( d ) : KoXmlElement();
01746 }
01747
01748 KoXmlText KoXmlNode::toText() const
01749 {
01750 return isText() ? KoXmlText( d ) : KoXmlText();
01751 }
01752
01753 KoXmlCDATASection KoXmlNode::toCDATASection() const
01754 {
01755 return isCDATASection() ? KoXmlCDATASection( d ) : KoXmlCDATASection();
01756 }
01757
01758 KoXmlDocument KoXmlNode::toDocument() const
01759 {
01760 if( isDocument() )
01761 return KoXmlDocument( d );
01762
01763 KoXmlDocument newDocument;
01764 newDocument.d->emptyDocument = false;
01765 return newDocument;
01766 }
01767
01768 void KoXmlNode::load( int depth )
01769 {
01770 d->loadChildren( depth );
01771 }
01772
01773 void KoXmlNode::unload()
01774 {
01775 d->unloadChildren();
01776 }
01777
01778 QDomNode KoXmlNode::asQDomNode( QDomDocument ownerDoc ) const
01779 {
01780 return d->asQDomNode( ownerDoc );
01781 }
01782
01783
01784
01785
01786
01787
01788
01789
01790 KoXmlElement::KoXmlElement(): KoXmlNode( new KoXmlNodeData )
01791 {
01792
01793 d->unref();
01794 }
01795
01796 KoXmlElement::~KoXmlElement()
01797 {
01798 if( d )
01799 if( d != &KoXmlNodeData::null )
01800 d->unref();
01801
01802 d = 0;
01803 }
01804
01805
01806 KoXmlElement::KoXmlElement( const KoXmlElement& element ): KoXmlNode( element.d )
01807 {
01808 }
01809
01810 KoXmlElement::KoXmlElement( KoXmlNodeData* data ): KoXmlNode( data )
01811 {
01812 }
01813
01814
01815 KoXmlElement& KoXmlElement::operator=( const KoXmlElement& element )
01816 {
01817 KoXmlNode::operator=( element );
01818 return *this;
01819 }
01820
01821 bool KoXmlElement::operator== ( const KoXmlElement& element ) const
01822 {
01823 if( isNull() || element.isNull() ) return false;
01824 return (d==element.d);
01825 }
01826
01827 bool KoXmlElement::operator!= ( const KoXmlElement& element ) const
01828 {
01829 if( isNull() && element.isNull() ) return false;
01830 if( isNull() || element.isNull() ) return true;
01831 return (d!=element.d);
01832 }
01833
01834 QString KoXmlElement::tagName() const
01835 {
01836 return isElement() ? ((KoXmlNodeData*)d)->tagName: QString();
01837 }
01838
01839 QString KoXmlElement::text() const
01840 {
01841 return d->text();
01842 }
01843
01844 QString KoXmlElement::attribute( const QString& name ) const
01845 {
01846 if( !isElement() )
01847 return QString();
01848
01849 if( !d->loaded)
01850 d->loadChildren();
01851
01852 return d->attribute( name, QString() );
01853 }
01854
01855 QString KoXmlElement::attribute( const QString& name,
01856 const QString& defaultValue ) const
01857 {
01858 if( !isElement() )
01859 return defaultValue;
01860
01861 if( !d->loaded)
01862 d->loadChildren();
01863
01864 return d->attribute( name, defaultValue );
01865 }
01866
01867 QString KoXmlElement::attributeNS( const QString& namespaceURI,
01868 const QString& localName, const QString& defaultValue ) const
01869 {
01870 if( !isElement() )
01871 return defaultValue;
01872
01873 if( !d->loaded)
01874 d->loadChildren();
01875
01876 KoXmlStringPair key( namespaceURI, localName );
01877 if( d->attrNS.contains( key ) )
01878 return d->attrNS[ key ];
01879 else
01880 return defaultValue;
01881
01882
01883 }
01884
01885 bool KoXmlElement::hasAttribute( const QString& name ) const
01886 {
01887 if( !d->loaded)
01888 d->loadChildren();
01889
01890 return isElement() ? d->hasAttribute( name ) : false;
01891 }
01892
01893 bool KoXmlElement::hasAttributeNS( const QString& namespaceURI,
01894 const QString& localName ) const
01895 {
01896 if( !d->loaded)
01897 d->loadChildren();
01898
01899 return isElement() ? d->hasAttributeNS( namespaceURI, localName ) : false;
01900 }
01901
01902
01903
01904
01905
01906
01907
01908 KoXmlText::KoXmlText(): KoXmlNode( new KoXmlNodeData )
01909 {
01910
01911 d->unref();
01912 }
01913
01914 KoXmlText::~KoXmlText()
01915 {
01916 if( d )
01917 if( d != &KoXmlNodeData::null )
01918 d->unref();
01919
01920 d = 0;
01921 }
01922
01923 KoXmlText::KoXmlText( const KoXmlText& text ): KoXmlNode( text.d )
01924 {
01925 }
01926
01927 KoXmlText::KoXmlText( KoXmlNodeData* data ): KoXmlNode( data )
01928 {
01929 }
01930
01931 bool KoXmlText::isText() const
01932 {
01933 return true;
01934 }
01935
01936 QString KoXmlText::data() const
01937 {
01938 return d->data();
01939 }
01940
01941 KoXmlText& KoXmlText::operator=( const KoXmlText& element )
01942 {
01943 KoXmlNode::operator=( element );
01944 return *this;
01945 }
01946
01947
01948
01949
01950
01951
01952
01953 KoXmlCDATASection::KoXmlCDATASection(): KoXmlText()
01954 {
01955 d->nodeType = KoXmlNode::CDATASectionNode;
01956 }
01957
01958 KoXmlCDATASection::~KoXmlCDATASection()
01959 {
01960 d->unref();
01961 d = 0;
01962 }
01963
01964 KoXmlCDATASection::KoXmlCDATASection( KoXmlNodeData* cdata ):
01965 KoXmlText( cdata )
01966 {
01967 }
01968
01969 bool KoXmlCDATASection::isCDATASection() const
01970 {
01971 return true;
01972 }
01973
01974 KoXmlCDATASection& KoXmlCDATASection::operator=( const KoXmlCDATASection& cdata )
01975 {
01976 KoXmlNode::operator=( cdata );
01977 return *this;
01978 }
01979
01980
01981
01982
01983
01984
01985
01986 KoXmlDocument::KoXmlDocument(): KoXmlNode()
01987 {
01988 d->emptyDocument = false;
01989 }
01990
01991 KoXmlDocument::~KoXmlDocument()
01992 {
01993 if( d )
01994 if( d != &KoXmlNodeData::null )
01995 d->unref();
01996
01997 d = 0;
01998 }
01999
02000 KoXmlDocument::KoXmlDocument( KoXmlNodeData* data ): KoXmlNode( data )
02001 {
02002 d->emptyDocument = true;
02003 }
02004
02005
02006 KoXmlDocument::KoXmlDocument( const KoXmlDocument& doc ): KoXmlNode( doc.d )
02007 {
02008 }
02009
02010
02011 KoXmlDocument& KoXmlDocument::operator=( const KoXmlDocument& doc )
02012 {
02013 KoXmlNode::operator=( doc );
02014 return *this;
02015 }
02016
02017
02018 bool KoXmlDocument::operator==( const KoXmlDocument& doc ) const
02019 {
02020 return( d==doc.d );
02021 }
02022
02023
02024 bool KoXmlDocument::operator!=( const KoXmlDocument& doc ) const
02025 {
02026 return( d!=doc.d );
02027 }
02028
02029 KoXmlElement KoXmlDocument::documentElement() const
02030 {
02031 d->loadChildren();
02032
02033 for( KoXmlNodeData* node=d->first; node; )
02034 {
02035 if( node->nodeType==KoXmlNode::ElementNode )
02036 return KoXmlElement( node );
02037 else node = node->next;
02038 }
02039
02040 return KoXmlElement();
02041 }
02042
02043 QString KoXmlDocument::nodeName() const
02044 {
02045 if( d->emptyDocument )
02046 return QLatin1String("#document");
02047 else
02048 return QString();
02049 }
02050
02051 void KoXmlDocument::clear()
02052 {
02053 KoXmlNode::clear();
02054 d->emptyDocument = false;
02055 }
02056
02057 bool KoXmlDocument::setContent( QXmlInputSource *source, QXmlReader *reader,
02058 QString* errorMsg, int* errorLine, int* errorColumn )
02059 {
02060 if( d->nodeType != KoXmlNode::DocumentNode )
02061 {
02062 d->unref();
02063 d = new KoXmlNodeData;
02064 d->nodeType = KoXmlNode::DocumentNode;
02065 }
02066
02067 return d->setContent( source, reader, errorMsg, errorLine, errorColumn );
02068 }
02069
02070
02071 bool KoXmlDocument::setContent( QIODevice* device, QString* errorMsg,
02072 int* errorLine, int* errorColumn )
02073 {
02074 return setContent( device, false, errorMsg, errorLine, errorColumn );
02075 }
02076
02077 bool KoXmlDocument::setContent( QIODevice* device, bool namespaceProcessing,
02078 QString* errorMsg, int* errorLine, int* errorColumn )
02079 {
02080 if( d->nodeType != KoXmlNode::DocumentNode )
02081 {
02082 d->unref();
02083 d = new KoXmlNodeData;
02084 d->nodeType = KoXmlNode::DocumentNode;
02085 }
02086
02087 QXmlSimpleReader reader;
02088 reader.setFeature( "http://xml.org/sax/features/namespaces", namespaceProcessing );
02089 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", !namespaceProcessing );
02090 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
02091
02092
02093
02094
02095 QXmlInputSource source( device );
02096 return d->setContent( &source, &reader, errorMsg, errorLine, errorColumn );
02097 }
02098
02099 bool KoXmlDocument::setContent( const QByteArray& text, bool namespaceProcessing,
02100 QString *errorMsg, int *errorLine, int *errorColumn )
02101 {
02102 QBuffer buffer;
02103 buffer.setData( text );
02104 return setContent( &buffer, namespaceProcessing, errorMsg, errorLine, errorColumn );
02105 }
02106
02107 bool KoXmlDocument::setContent(const QString& text, bool namespaceProcessing,
02108 QString *errorMsg, int *errorLine, int *errorColumn)
02109 {
02110 if( d->nodeType != KoXmlNode::DocumentNode )
02111 {
02112 d->unref();
02113 d = new KoXmlNodeData;
02114 d->nodeType = KoXmlNode::DocumentNode;
02115 }
02116
02117 QXmlInputSource source;
02118 source.setData(text);
02119 return d->setContent( &source, namespaceProcessing, errorMsg, errorLine, errorColumn );
02120 }
02121
02122 bool KoXmlDocument::setContent(const QString& text,
02123 QString *errorMsg, int *errorLine, int *errorColumn)
02124 {
02125 return setContent( text, false, errorMsg, errorLine, errorColumn );
02126 }
02127
02128 #endif
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148 #define KOXML_BUFSIZE 16*1024 // should be adequate
02149
02150 KoXmlInputSource::KoXmlInputSource(QIODevice *dev): QXmlInputSource(),
02151 device( dev )
02152 {
02153 int mib = 106;
02154 decoder = QTextCodec::codecForMib( mib )->makeDecoder();
02155
02156 stringLength = 0;
02157 stringIndex = 0;
02158 buffer = new char[KOXML_BUFSIZE];
02159
02160 reset();
02161 }
02162
02163 KoXmlInputSource::~KoXmlInputSource()
02164 {
02165 delete decoder;
02166 delete [] buffer;
02167 }
02168
02169 void KoXmlInputSource::setData(const QString& dat)
02170 {
02171 Q_UNUSED(dat);
02172 }
02173
02174 void KoXmlInputSource::setData(const QByteArray& dat)
02175 {
02176 Q_UNUSED(dat);
02177 }
02178
02179 void KoXmlInputSource::fetchData()
02180 {
02181 }
02182
02183 QString KoXmlInputSource::data() const
02184 {
02185 return QString();
02186 }
02187
02188 QChar KoXmlInputSource::next()
02189 {
02190 if(stringIndex >= stringLength)
02191 {
02192
02193 qint64 bytes = device->read( buffer, KOXML_BUFSIZE );
02194 if( bytes == 0 )
02195 return EndOfDocument;
02196
02197 stringData = decoder->toUnicode( buffer, bytes );
02198 stringLength = stringData.length();
02199 stringIndex = 0;
02200 }
02201
02202 return stringData[stringIndex++];
02203 }
02204
02205 void KoXmlInputSource::reset()
02206 {
02207 device->seek(0);
02208 }
02209
02210 QString KoXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
02211 {
02212 Q_UNUSED( data );
02213 Q_UNUSED( beginning );
02214 return QString();
02215 }
02216
02217
02218
02219
02220
02221
02222
02223 KoXmlElement KoXml::namedItemNS( const KoXmlNode& node, const char* nsURI,
02224 const char* localName )
02225 {
02226 #ifdef KOXML_USE_QDOM
02227
02228 KoXmlNode n = node.firstChild();
02229 for ( ; !n.isNull(); n = n.nextSibling() ) {
02230 if ( n.isElement() && n.localName() == localName &&
02231 n.namespaceURI() == nsURI )
02232 return n.toElement();
02233 }
02234 return KoXmlElement();
02235 #else
02236 return node.namedItemNS( nsURI, localName).toElement();
02237 #endif
02238 }
02239
02240 void KoXml::load( KoXmlNode& node, int depth )
02241 {
02242 #ifdef KOXML_USE_QDOM
02243
02244 Q_UNUSED( node );
02245 Q_UNUSED( depth );
02246 #else
02247 node.load( depth );
02248 #endif
02249 }
02250
02251
02252 void KoXml::unload( KoXmlNode& node )
02253 {
02254 #ifdef KOXML_USE_QDOM
02255
02256 Q_UNUSED( node );
02257 #else
02258 node.unload();
02259 #endif
02260 }
02261
02262 int KoXml::childNodesCount( const KoXmlNode& node )
02263 {
02264 #ifdef KOXML_USE_QDOM
02265 return node.childNodes().count();
02266 #else
02267
02268
02269 return node.childNodesCount();
02270 #endif
02271 }
02272
02273 QDomNode KoXml::asQDomNode( QDomDocument ownerDoc, const KoXmlNode& node )
02274 {
02275 #ifdef KOXML_USE_QDOM
02276 Q_UNUSED( ownerDoc );
02277 return node;
02278 #else
02279 return node.asQDomNode( ownerDoc );
02280 #endif
02281 }
02282
02283 QDomElement KoXml::asQDomElement( QDomDocument ownerDoc, const KoXmlElement& element )
02284 {
02285 return KoXml::asQDomNode( ownerDoc, element ).toElement();
02286 }
02287
02288 QDomDocument KoXml::asQDomDocument( QDomDocument ownerDoc, const KoXmlDocument& document )
02289 {
02290 return KoXml::asQDomNode( ownerDoc, document ).toDocument();
02291 }
02292
02293 bool KoXml::setDocument( KoXmlDocument& doc, QIODevice* device,
02294 bool namespaceProcessing, QString* errorMsg, int* errorLine,
02295 int* errorColumn )
02296 {
02297 QXmlSimpleReader reader;
02298 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), namespaceProcessing);
02299 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), !namespaceProcessing);
02300 reader.setFeature(QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData"), false);
02301
02302 KoXmlInputSource* source = new KoXmlInputSource( device );
02303 bool result = doc.setContent( source, &reader, errorMsg, errorLine, errorColumn);
02304 delete source;
02305 return result;
02306 }
02307
02308 bool KoXml::setDocument( KoXmlDocument& doc, QIODevice* device,
02309 QXmlSimpleReader* reader, QString* errorMsg, int* errorLine, int* errorColumn )
02310 {
02311 KoXmlInputSource* source = new KoXmlInputSource( device );
02312 bool result = doc.setContent( source, reader, errorMsg, errorLine, errorColumn);
02313 delete source;
02314 return result;
02315 }
02316