F:/KPlato/koffice/libs/store/tests/koxmlreadertest.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2005-2006 Ariya Hidayat <ariya@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 */
00018 
00019 //  koxmlreadertest.cpp - test KoXml classes
00020 //  Ariya Hidayat, November 2005, last updated October 2006
00021 
00022 #include <QBuffer>
00023 #include <QFile>
00024 #include <QDateTime>
00025 #include <QProcess>
00026 #include <QString>
00027 #include <QTextStream>
00028 
00029 #include <KoXmlReader.h>
00030 
00031 #include <QtXml>
00032 
00033 #define CHECK(x,y)  check(__FILE__,__LINE__,#x,x,y)
00034 
00035 static int testCount = 0;
00036 static int testFailed = 0;
00037 
00038 template<typename T>
00039 void check( const char *file, int line, const char* msg, 
00040 const T& result, const T& expected )
00041 {
00042   testCount++;
00043   if( result != expected )
00044   {
00045     testFailed++;
00046     QString message;
00047     QTextStream ts( &message, QIODevice::WriteOnly );
00048     ts << msg;
00049     ts << "  Result:";
00050     ts << result;
00051     ts << ", ";
00052     ts << "Expected:";
00053     ts << expected;
00054     printf( "%s [%d]: %s\n", file, line, message.toLatin1().data() );
00055   }
00056 }
00057 
00058 void check( const char *file, int line, const char* msg, bool result, 
00059 bool expected )
00060 {
00061   testCount++;
00062   if( result != expected )
00063   {
00064     testFailed++;
00065     QString message;
00066     QTextStream ts( &message, QIODevice::WriteOnly );
00067     ts << msg;
00068     ts << "  Result: ";
00069     if( result ) ts << "True"; else ts << "False";
00070     ts << ", ";
00071     ts << "Expected: ";
00072     if( expected ) ts << "True"; else ts << "False";
00073 
00074     printf( "%s [%d]: %s\n", file, line, message.toLatin1().data() );
00075   }
00076 }
00077 
00078 void testNode()
00079 {
00080   QString errorMsg;
00081   int errorLine = 0;
00082   int errorColumn = 0;
00083 
00084   QBuffer xmldevice;
00085   xmldevice.open( QIODevice::WriteOnly );
00086   QTextStream xmlstream( &xmldevice );
00087   xmlstream << "<earth>";
00088   xmlstream << " <continents>";
00089   xmlstream << "  <asia/>";
00090   xmlstream << "  <africa/>";
00091   xmlstream << "  <europe/>";
00092   xmlstream << "  <america/>";
00093   xmlstream << "  <australia/>";
00094   xmlstream << "  <antartic/>";
00095   xmlstream << " </continents>";
00096   xmlstream << " <oceans>";
00097   xmlstream << "  <pacific/>";
00098   xmlstream << "  <atlantic/>";
00099   xmlstream << " </oceans>";
00100   xmlstream << "</earth>";
00101   xmldevice.close();
00102 
00103   KoXmlDocument doc;
00104   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00105   CHECK( errorMsg.isEmpty(), true );
00106   CHECK( errorLine, 0 );
00107   CHECK( errorColumn, 0 );
00108 
00109   // null node
00110   KoXmlNode node1;
00111   CHECK( node1.nodeName(), QString() );
00112   CHECK( node1.isNull(), true );
00113   CHECK( node1.isElement(), false );
00114   CHECK( node1.isDocument(), false );
00115   CHECK( node1.ownerDocument().isNull(), true );
00116   CHECK( node1.parentNode().isNull(), true );
00117   CHECK( node1.hasChildNodes(), false );
00118   CHECK( KoXml::childNodesCount(node1), 0 );
00119   CHECK( node1.firstChild().isNull(), true );
00120   CHECK( node1.lastChild().isNull(), true );
00121   CHECK( node1.previousSibling().isNull(), true );
00122   CHECK( node1.nextSibling().isNull(), true );
00123   
00124   // compare with another null node
00125   KoXmlNode node2;
00126   CHECK( node2.isNull(), true );
00127   CHECK( node1==node2, true );
00128   CHECK( node1!=node2, false );
00129 
00130   // a node which is a document
00131   KoXmlNode node3 = doc;
00132   CHECK( node3.nodeName(), QString("#document") );
00133   CHECK( node3.isNull(), false );
00134   CHECK( node3.isElement(), false );
00135   CHECK( node3.isText(), false );
00136   CHECK( node3.isDocument(), true );
00137   CHECK( node3.ownerDocument().isNull(), false );
00138   CHECK( node3.ownerDocument()==doc, true );
00139   CHECK( node3.toDocument()==doc, true );
00140   CHECK( KoXml::childNodesCount(node3), 1 );
00141 
00142   // convert to document and the compare
00143   KoXmlDocument doc2 = node3.toDocument();
00144   CHECK( doc2.nodeName(), QString("#document") );
00145   CHECK( doc2.isNull(), false );
00146   CHECK( doc2.isDocument(), true );
00147   CHECK( node3==doc2, true );
00148   CHECK( KoXml::childNodesCount(doc2), 1 );
00149 
00150   // a document is of course can't be converted to element
00151   KoXmlElement invalidElement = node3.toElement();
00152   CHECK( invalidElement.nodeName(), QString() );
00153   CHECK( invalidElement.isNull(), true );
00154   CHECK( invalidElement.isElement(), false );
00155   CHECK( invalidElement.isText(), false );
00156   CHECK( invalidElement.isDocument(), false );
00157 
00158   // clear() makes it a null node again
00159   node3.clear();
00160   CHECK( node3.isNull(), true );
00161   CHECK( node3.nodeName(), QString() );
00162   CHECK( node3.isElement(), false );
00163   CHECK( node3.isText(), false );
00164   CHECK( node3.isDocument(), false );
00165   CHECK( node3.ownerDocument().isNull(), true );
00166   CHECK( node1==node3, true );
00167   CHECK( node1!=node3, false );
00168 
00169   // a node which is an element for <earth>
00170   KoXmlNode node4 = doc.firstChild();
00171   CHECK( node4.isNull(), false );
00172   CHECK( node4.isElement(), true );
00173   CHECK( node4.isText(), false );
00174   CHECK( node4.isDocument(), false );
00175   CHECK( node4.hasChildNodes(), true );
00176   CHECK( KoXml::childNodesCount(node4), 2 );
00177   CHECK( node4.ownerDocument()==doc, true );
00178   CHECK( node4.toElement()==doc.firstChild().toElement(), true );
00179 
00180   // clear() makes it a null node again
00181   node4.clear();
00182   CHECK( node4.isNull(), true );
00183   CHECK( node4.isElement(), false );
00184   CHECK( node4.isText(), false );
00185   CHECK( node4.isDocument(), false );
00186   CHECK( node4==node1, true );
00187   CHECK( node4!=node1, false );
00188   CHECK( KoXml::childNodesCount(node4), 0 );
00189 
00190   // a node which is an element for <continents>
00191   KoXmlNode node5 = doc.firstChild().firstChild();
00192   CHECK( node5.nodeName(), QString("continents") );
00193   CHECK( node5.isNull(), false );
00194   CHECK( node5.isElement(), true );
00195   CHECK( node5.isText(), false );
00196   CHECK( node5.isDocument(), false );
00197   CHECK( node5.hasChildNodes(), true );
00198   CHECK( KoXml::childNodesCount(node5), 6 );
00199   CHECK( node5.ownerDocument()==doc, true );
00200 
00201   // convert to element and the compare
00202   KoXmlElement continentsElement = node5.toElement();
00203   CHECK( node5==continentsElement, true );
00204   CHECK( continentsElement.isNull(), false );
00205   CHECK( continentsElement.isElement(), true );
00206   CHECK( continentsElement.isText(), false );
00207   CHECK( continentsElement.hasChildNodes(), true );
00208   CHECK( KoXml::childNodesCount(continentsElement), 6 );
00209   CHECK( continentsElement.ownerDocument()==doc, true );
00210 
00211   // and it doesn't make sense to convert that node to document
00212   KoXmlDocument invalidDoc = node5.toDocument();
00213   CHECK( invalidDoc.isNull(), true );
00214   CHECK( invalidDoc.isElement(), false );
00215   CHECK( invalidDoc.isText(), false );
00216   CHECK( invalidDoc.isDocument(), false );
00217 
00218   // node for <europe> using namedItem() function
00219   KoXmlNode europeNode = continentsElement.namedItem( QString("europe") );
00220   CHECK( europeNode.nodeName(), QString("europe") );
00221   CHECK( europeNode.isNull(), false );
00222   CHECK( europeNode.isElement(), true );
00223   CHECK( europeNode.isText(), false );
00224   CHECK( europeNode.hasChildNodes(), false );
00225   CHECK( KoXml::childNodesCount(europeNode), 0 );
00226   CHECK( europeNode.ownerDocument()==doc, true );
00227 
00228   // search non-existing node
00229   KoXmlNode fooNode = continentsElement.namedItem( QString("foobar") );
00230   CHECK( fooNode.isNull(), true );
00231   CHECK( fooNode.isElement(), false );
00232   CHECK( fooNode.isText(), false );
00233   CHECK( fooNode.isCDATASection(), false );
00234   CHECK( KoXml::childNodesCount(fooNode), 0 );
00235 }
00236 
00237 void testElement()
00238 {
00239   QString errorMsg;
00240   int errorLine = 0;
00241   int errorColumn = 0;
00242 
00243   QBuffer xmldevice;
00244   xmldevice.open( QIODevice::WriteOnly );
00245   QTextStream xmlstream( &xmldevice );
00246   xmlstream << "<html>";
00247   xmlstream << "<body bgcolor=\"#000\">";
00248   xmlstream << "<p>";
00249   xmlstream << "Hello, world!";
00250   xmlstream << "</p>";
00251   xmlstream << "</body>";
00252   xmlstream << "</html>";
00253   xmldevice.close();
00254 
00255   KoXmlDocument doc;
00256   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00257   CHECK( errorMsg.isEmpty(), true );
00258   CHECK( errorLine, 0 );
00259   CHECK( errorColumn, 0 );
00260 
00261   // element for <html> 
00262   KoXmlElement rootElement;
00263   rootElement = doc.documentElement();
00264   CHECK( rootElement.nodeName(), QString("html") );
00265   CHECK( rootElement.isNull(), false );
00266   CHECK( rootElement.isElement(), true );
00267   CHECK( rootElement.isDocument(), false );
00268   CHECK( rootElement.ownerDocument().isNull(), false );
00269   CHECK( rootElement.ownerDocument()==doc, true );
00270   CHECK( rootElement.parentNode().isNull(), false );
00271   CHECK( rootElement.parentNode().toDocument()==doc, true );
00272   CHECK( rootElement.hasChildNodes(), true );
00273   CHECK( KoXml::childNodesCount(rootElement), 1 );
00274   CHECK( rootElement.tagName(), QString("html") );
00275   CHECK( rootElement.prefix().isNull(), true );
00276  
00277   // element for <body> 
00278   KoXmlElement bodyElement;
00279   bodyElement = rootElement.firstChild().toElement();
00280   CHECK( bodyElement.nodeName(), QString("body") );
00281   CHECK( bodyElement.isNull(), false );
00282   CHECK( bodyElement.isElement(), true );
00283   CHECK( bodyElement.isDocument(), false );
00284   CHECK( bodyElement.ownerDocument().isNull(), false );
00285   CHECK( bodyElement.ownerDocument()==doc, true );
00286   CHECK( bodyElement.parentNode().isNull(), false );
00287   CHECK( bodyElement.parentNode()==rootElement, true );
00288   CHECK( bodyElement.hasChildNodes(), true );
00289   CHECK( KoXml::childNodesCount(bodyElement), 1 );
00290   CHECK( bodyElement.tagName(), QString("body") );
00291   CHECK( bodyElement.prefix().isNull(), true );
00292   CHECK( bodyElement.hasAttribute("bgcolor"), true );
00293   CHECK( bodyElement.attribute("bgcolor"), QString("#000") );
00294 
00295   // a shared copy of <body>, will still have access to attribute bgcolor
00296   KoXmlElement body2Element;
00297   body2Element = bodyElement;
00298   CHECK( body2Element.nodeName(), QString("body") );
00299   CHECK( body2Element.isNull(), false );
00300   CHECK( body2Element.isElement(), true );
00301   CHECK( body2Element.isDocument(), false );
00302   CHECK( body2Element.ownerDocument().isNull(), false );
00303   CHECK( body2Element.ownerDocument()==doc, true );
00304   CHECK( body2Element==bodyElement, true );
00305   CHECK( body2Element!=bodyElement, false );
00306   CHECK( body2Element.hasChildNodes(), true );
00307   CHECK( KoXml::childNodesCount(body2Element), 1 );
00308   CHECK( body2Element.tagName(), QString("body") );
00309   CHECK( body2Element.prefix().isNull(), true );
00310   CHECK( body2Element.hasAttribute("bgcolor"), true );
00311   CHECK( body2Element.attribute("bgcolor"), QString("#000") );
00312 
00313   // empty element, by default constructor
00314   KoXmlElement testElement; 
00315   CHECK( testElement.nodeName(), QString() );
00316   CHECK( testElement.isNull(), true );
00317   CHECK( testElement.isElement(), false );
00318   CHECK( testElement.isDocument(), false );
00319   CHECK( testElement.ownerDocument().isNull(), true );
00320   CHECK( testElement.ownerDocument()!=doc, true );
00321   CHECK( testElement==rootElement, false );
00322   CHECK( testElement!=rootElement, true );
00323   CHECK( testElement.parentNode().isNull(), true );
00324   CHECK( testElement.hasChildNodes(), false );
00325   CHECK( KoXml::childNodesCount(testElement), 0 );
00326 
00327   // check assignment operator
00328   testElement = rootElement;
00329   CHECK( testElement.nodeName(), QString("html") );
00330   CHECK( testElement.isNull(), false );
00331   CHECK( testElement.isElement(), true );
00332   CHECK( testElement.isDocument(), false );
00333   CHECK( testElement==rootElement, true );
00334   CHECK( testElement!=rootElement, false );
00335   CHECK( testElement.parentNode().isNull(), false );
00336   CHECK( testElement.parentNode().toDocument()==doc, true );
00337   CHECK( testElement.tagName(), QString("html") );
00338   CHECK( testElement.prefix().isNull(), true );
00339   CHECK( KoXml::childNodesCount(testElement), 1 );
00340 
00341   // assigned from another empty element
00342   testElement = KoXmlElement();
00343   CHECK( testElement.isNull(), true );
00344   CHECK( testElement!=rootElement, true );
00345 
00346   // assigned from <body>
00347   testElement = bodyElement;
00348   CHECK( testElement.isNull(), false );
00349   CHECK( testElement.isElement(), true );
00350   CHECK( testElement.isDocument(), false );
00351   CHECK( testElement.ownerDocument().isNull(), false );
00352   CHECK( testElement.ownerDocument()==doc, true );
00353   CHECK( testElement==bodyElement, true );
00354   CHECK( testElement.parentNode().isNull(), false );
00355   CHECK( testElement.tagName(), QString("body") );
00356   CHECK( testElement.prefix().isNull(), true );
00357   CHECK( testElement.hasChildNodes(), true );
00358   CHECK( KoXml::childNodesCount(testElement), 1 );
00359 
00360   // copy constructor  
00361   KoXmlElement dummyElement( rootElement ); 
00362   CHECK( dummyElement.isNull(), false );
00363   CHECK( dummyElement.isElement(), true );
00364   CHECK( dummyElement.isDocument(), false );
00365   CHECK( dummyElement.ownerDocument().isNull(), false );
00366   CHECK( dummyElement.ownerDocument()==doc, true );
00367   CHECK( dummyElement==rootElement, true );
00368   CHECK( dummyElement.parentNode().isNull(), false );
00369   CHECK( dummyElement.hasChildNodes(), true );
00370   CHECK( KoXml::childNodesCount(dummyElement), 1 );
00371   CHECK( dummyElement.tagName(), QString("html") );
00372   CHECK( dummyElement.prefix().isNull(), true );
00373 
00374   // clear() turns element to null node
00375   dummyElement.clear();
00376   CHECK( dummyElement.isNull(), true );
00377   CHECK( dummyElement.isElement(), false );
00378   CHECK( dummyElement.isDocument(), false );
00379   CHECK( dummyElement.ownerDocument().isNull(), true );
00380   CHECK( dummyElement.ownerDocument()==doc, false );
00381   CHECK( dummyElement.hasChildNodes(), false );
00382   CHECK( KoXml::childNodesCount(dummyElement), 0 );
00383   CHECK( dummyElement==rootElement, false );
00384   CHECK( dummyElement!=rootElement, true );
00385   
00386   // check for plain null node converted to element
00387   KoXmlNode dummyNode;
00388   dummyElement = dummyNode.toElement();
00389   CHECK( dummyElement.isNull(), true );
00390   CHECK( dummyElement.isElement(), false );
00391   CHECK( dummyElement.isDocument(), false );
00392   CHECK( dummyElement.ownerDocument().isNull(), true );
00393   CHECK( dummyElement.hasChildNodes(), false );
00394   CHECK( KoXml::childNodesCount(dummyElement), 0 );
00395   CHECK( dummyElement.ownerDocument()==doc, false );
00396 }
00397 
00398 void testAttributes()
00399 {
00400   QString errorMsg;
00401   int errorLine = 0;
00402   int errorColumn = 0;
00403 
00404   QBuffer xmldevice;
00405   xmldevice.open( QIODevice::WriteOnly );
00406   QTextStream xmlstream( &xmldevice );
00407   xmlstream << "<p>";
00408   xmlstream << "<img src=\"foo.png\" width=\"300\" height=\"150\"/>";
00409   xmlstream << "</p>";
00410   xmldevice.close();
00411 
00412   KoXmlDocument doc;
00413   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00414   CHECK( errorMsg.isEmpty(), true );
00415   CHECK( errorLine, 0 );
00416   CHECK( errorColumn, 0 );
00417   
00418   KoXmlElement rootElement;
00419   rootElement = doc.documentElement();
00420   CHECK( rootElement.isNull(), false );
00421   CHECK( rootElement.isElement(), true );
00422   CHECK( rootElement.parentNode().isNull(), false );
00423   CHECK( rootElement.parentNode().toDocument()==doc, true );
00424   CHECK( rootElement.tagName(), QString("p") );
00425   CHECK( rootElement.prefix().isNull(), true );
00426   CHECK( KoXml::childNodesCount(rootElement), 1 );
00427 
00428   KoXmlElement imgElement;
00429   imgElement = rootElement.firstChild().toElement();
00430   CHECK( imgElement.isNull(), false );
00431   CHECK( imgElement.isElement(), true );
00432   CHECK( imgElement.tagName(), QString("img") );
00433   CHECK( imgElement.prefix().isNull(), true );
00434   CHECK( KoXml::childNodesCount(imgElement), 0 );
00435   CHECK( imgElement.hasAttribute("src"), true );
00436   CHECK( imgElement.hasAttribute("width"), true );
00437   CHECK( imgElement.hasAttribute("height"), true );
00438   CHECK( imgElement.hasAttribute("non-exist"), false );
00439   CHECK( imgElement.hasAttribute("SRC"), false );
00440   CHECK( imgElement.attribute("src"), QString("foo.png") );
00441   CHECK( imgElement.attribute("width"), QString("300") );
00442   CHECK( imgElement.attribute("width").toInt(), 300 );
00443   CHECK( imgElement.attribute("height"), QString("150") );
00444   CHECK( imgElement.attribute("height").toInt(), 150 );
00445   CHECK( imgElement.attribute("border").isEmpty(), true );
00446   CHECK( imgElement.attribute("border","0").toInt(), 0 );
00447   CHECK( imgElement.attribute("border","-1").toInt(), -1 );
00448 }
00449 
00450 void testText()
00451 {
00452   QString errorMsg;
00453   int errorLine = 0;
00454   int errorColumn = 0;
00455 
00456   QBuffer xmldevice;
00457   xmldevice.open( QIODevice::WriteOnly );
00458   QTextStream xmlstream( &xmldevice );
00459   xmlstream << "<p>";
00460   xmlstream << "Hello ";
00461   xmlstream << "<b>world</b>";
00462   xmlstream << "</p>";
00463   xmldevice.close();
00464 
00465   KoXmlDocument doc;
00466   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00467   CHECK( errorMsg.isEmpty(), true );
00468   CHECK( errorLine, 0 );
00469   CHECK( errorColumn, 0 );
00470 
00471   // element for <p> 
00472   KoXmlElement parElement;
00473   parElement = doc.documentElement();
00474   CHECK( parElement.isNull(), false );
00475   CHECK( parElement.isElement(), true );
00476   CHECK( parElement.isText(), false );
00477   CHECK( parElement.isDocument(), false );
00478   CHECK( parElement.ownerDocument().isNull(), false );
00479   CHECK( parElement.ownerDocument()==doc, true );
00480   CHECK( parElement.parentNode().isNull(), false );
00481   CHECK( parElement.parentNode().toDocument()==doc, true );
00482   CHECK( parElement.hasChildNodes(), true );
00483   CHECK( KoXml::childNodesCount(parElement), 2 ); // <b> and text node "Hello "
00484   CHECK( parElement.tagName(), QString("p") );
00485   CHECK( parElement.prefix().isNull(), true );
00486   CHECK( parElement.text(), QString("Hello world") );
00487 
00488   // node for "Hello"
00489   KoXmlNode helloNode;
00490   helloNode = parElement.firstChild();
00491   CHECK( helloNode.nodeName(), QString("#text") );
00492   CHECK( helloNode.isNull(), false );
00493   CHECK( helloNode.isElement(), false );
00494   CHECK( helloNode.isText(), true );
00495   CHECK( helloNode.isDocument(), false );
00496   CHECK( helloNode.hasChildNodes(), false );
00497   CHECK( KoXml::childNodesCount(helloNode), 0 );
00498   
00499   // "Hello" text
00500   KoXmlText helloText;
00501   helloText = helloNode.toText();
00502   CHECK( helloText.nodeName(), QString("#text") );
00503   CHECK( helloText.isNull(), false );
00504   CHECK( helloText.isElement(), false );
00505   CHECK( helloText.isText(), true );
00506   CHECK( helloText.isDocument(), false );
00507   CHECK( helloText.data(), QString("Hello ") );
00508   CHECK( KoXml::childNodesCount(helloText), 0 );
00509 
00510   // shared copy of the text
00511   KoXmlText hello2Text;
00512   hello2Text = helloText;
00513   CHECK( hello2Text.isNull(), false );
00514   CHECK( hello2Text.isElement(), false );
00515   CHECK( hello2Text.isText(), true );
00516   CHECK( hello2Text.isDocument(), false );
00517   CHECK( hello2Text.data(), QString("Hello ") );
00518   CHECK( KoXml::childNodesCount(hello2Text), 0 );
00519 
00520   // element for <b>
00521   KoXmlElement boldElement;
00522   boldElement = helloNode.nextSibling().toElement();
00523   CHECK( boldElement.isNull(), false );
00524   CHECK( boldElement.isElement(), true );
00525   CHECK( boldElement.isText(), false );
00526   CHECK( boldElement.isDocument(), false );
00527   CHECK( boldElement.ownerDocument().isNull(), false );
00528   CHECK( boldElement.ownerDocument()==doc, true );
00529   CHECK( boldElement.parentNode().isNull(), false );
00530   CHECK( boldElement.hasChildNodes(), true );
00531   CHECK( KoXml::childNodesCount(boldElement), 1 ); // text node "world"
00532   CHECK( boldElement.tagName(), QString("b") );
00533   CHECK( boldElement.prefix().isNull(), true );
00534 
00535   // "world" text
00536   KoXmlText worldText;
00537   worldText = boldElement.firstChild().toText();
00538   CHECK( worldText.isNull(), false );
00539   CHECK( worldText.isElement(), false );
00540   CHECK( worldText.isText(), true );
00541   CHECK( worldText.isDocument(), false );
00542   CHECK( worldText.data(), QString("world") );
00543   CHECK( KoXml::childNodesCount(worldText), 0 );
00544 }
00545 
00546 void testCDATA()
00547 {
00548   QString errorMsg;
00549   int errorLine = 0;
00550   int errorColumn = 0;
00551 
00552   QBuffer xmldevice;
00553   xmldevice.open( QIODevice::WriteOnly );
00554   QTextStream xmlstream( &xmldevice );
00555   xmlstream << "<p>";
00556   xmlstream << "Hello ";
00557   xmlstream << "<![CDATA[world]]>";
00558   xmlstream << "</p>";
00559   xmldevice.close();
00560 
00561   KoXmlDocument doc;
00562   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00563   CHECK( errorMsg.isEmpty(), true );
00564   CHECK( errorLine, 0 );
00565   CHECK( errorColumn, 0 );
00566 
00567   // element for <p> 
00568   KoXmlElement parElement;
00569   parElement = doc.documentElement();
00570   CHECK( parElement.isNull(), false );
00571   CHECK( parElement.isElement(), true );
00572   CHECK( parElement.isText(), false );
00573   CHECK( parElement.isDocument(), false );
00574   CHECK( parElement.ownerDocument().isNull(), false );
00575   CHECK( parElement.ownerDocument()==doc, true );
00576   CHECK( parElement.parentNode().isNull(), false );
00577   CHECK( parElement.parentNode().toDocument()==doc, true );
00578   CHECK( parElement.hasChildNodes(), true );
00579   CHECK( KoXml::childNodesCount(parElement), 2 );
00580   CHECK( parElement.tagName(), QString("p") );
00581   CHECK( parElement.prefix().isNull(), true );
00582   CHECK( parElement.text(), QString("Hello world") );
00583 
00584   // node for "Hello"
00585   KoXmlNode helloNode;
00586   helloNode = parElement.firstChild();
00587   CHECK( helloNode.isNull(), false );
00588   CHECK( helloNode.isElement(), false );
00589   CHECK( helloNode.isText(), true );
00590   CHECK( helloNode.isDocument(), false );
00591 
00592   // "Hello" text
00593   KoXmlText helloText;
00594   helloText = helloNode.toText();
00595   CHECK( helloText.isNull(), false );
00596   CHECK( helloText.isElement(), false );
00597   CHECK( helloText.isText(), true );
00598   CHECK( helloText.isDocument(), false );
00599   CHECK( helloText.data(), QString("Hello ") );
00600 
00601   // node for CDATA "world!"
00602   // Note: isText() is also true for CDATA
00603   KoXmlNode worldNode;
00604   worldNode = helloNode.nextSibling();
00605   CHECK( worldNode.nodeName(), QString("#cdata-section") );
00606   CHECK( worldNode.isNull(), false );
00607   CHECK( worldNode.isElement(), false );
00608   CHECK( worldNode.isText(), true );
00609   CHECK( worldNode.isCDATASection(), true );
00610   CHECK( worldNode.isDocument(), false );
00611 
00612   // CDATA section for "world!"
00613   // Note: isText() is also true for CDATA
00614   KoXmlCDATASection worldCDATA;
00615   worldCDATA = worldNode.toCDATASection();
00616   CHECK( worldCDATA.nodeName(), QString("#cdata-section") );
00617   CHECK( worldCDATA.isNull(), false );
00618   CHECK( worldCDATA.isElement(), false );
00619   CHECK( worldCDATA.isText(), true );
00620   CHECK( worldCDATA.isCDATASection(), true );
00621   CHECK( worldCDATA.isDocument(), false );
00622   CHECK( worldCDATA.data(), QString("world") );
00623 }
00624 
00625 void testDocument()
00626 {
00627   QString errorMsg;
00628   int errorLine = 0;
00629   int errorColumn = 0;
00630 
00631   QBuffer xmldevice;
00632   xmldevice.open( QIODevice::WriteOnly );
00633   QTextStream xmlstream( &xmldevice );
00634   xmlstream << "<koffice>";
00635   xmlstream << "  <kword/>\n";
00636   xmlstream << "  <kpresenter/>\n";
00637   xmlstream << "  <krita/>\n";
00638   xmlstream << "</koffice>";
00639   xmldevice.close();
00640 
00641   KoXmlDocument doc;
00642 
00643   // empty document
00644   CHECK( doc.nodeName(), QString() );
00645   CHECK( doc.isNull(), true );
00646   CHECK( doc.isElement(), false );
00647   CHECK( doc.isDocument(), false );
00648   CHECK( doc.parentNode().isNull(), true );
00649   CHECK( doc.firstChild().isNull(), true );
00650   CHECK( doc.lastChild().isNull(), true );
00651   CHECK( doc.previousSibling().isNull(), true );
00652   CHECK( doc.nextSibling().isNull(), true );
00653 
00654   // now give something as the content
00655   CHECK( doc.setContent(&xmldevice,&errorMsg,&errorLine,&errorColumn ), true );
00656   CHECK( errorMsg.isEmpty(), true );
00657   CHECK( errorLine, 0 );
00658   CHECK( errorColumn, 0 );
00659 
00660   // this document has something already
00661   CHECK( doc.nodeName(), QString("#document") );
00662   CHECK( doc.isNull(), false );
00663   CHECK( doc.isElement(), false );
00664   CHECK( doc.isDocument(), true );
00665   CHECK( doc.parentNode().isNull(), true );
00666   CHECK( doc.firstChild().isNull(), false );
00667   CHECK( doc.lastChild().isNull(), false );
00668   CHECK( doc.previousSibling().isNull(), true );
00669   CHECK( doc.nextSibling().isNull(), true );
00670 
00671   // make sure its children are fine
00672   KoXmlElement rootElement;
00673   rootElement = doc.firstChild().toElement();
00674   CHECK( rootElement.isNull(), false );
00675   CHECK( rootElement.isElement(), true );
00676   CHECK( rootElement.isDocument(), false );
00677   CHECK( rootElement.parentNode().isNull(), false );
00678   CHECK( rootElement.parentNode().toDocument()==doc, true );
00679   rootElement = doc.lastChild().toElement();
00680   CHECK( rootElement.isNull(), false );
00681   CHECK( rootElement.isElement(), true );
00682   CHECK( rootElement.isDocument(), false );
00683   CHECK( rootElement.parentNode().isNull(), false );
00684   CHECK( rootElement.parentNode().toDocument()==doc, true );
00685 
00686   // clear() converts it into null node
00687   doc.clear();
00688   CHECK( doc.nodeName(), QString() );
00689   CHECK( doc.isNull(), true );
00690   CHECK( doc.isElement(), false );
00691   CHECK( doc.isDocument(), false );
00692   CHECK( doc.parentNode().isNull(), true );
00693   CHECK( doc.firstChild().isNull(), true );
00694   CHECK( doc.lastChild().isNull(), true );
00695   CHECK( doc.previousSibling().isNull(), true );
00696   CHECK( doc.nextSibling().isNull(), true );
00697 
00698   // assigned from another empty document
00699   doc = KoXmlDocument();
00700   CHECK( doc.nodeName(), QString() );
00701   CHECK( doc.nodeName().isEmpty(), true );
00702   CHECK( doc.isNull(), true );
00703   CHECK( doc.isElement(), false );
00704   CHECK( doc.isDocument(), false );
00705   CHECK( doc.parentNode().isNull(), true );
00706 }
00707 
00708 void testNamespace()
00709 {
00710   QString errorMsg;
00711   int errorLine = 0;
00712   int errorColumn = 0;
00713 
00714   QBuffer xmldevice;
00715   xmldevice.open( QIODevice::WriteOnly );
00716   QTextStream xmlstream( &xmldevice );
00717   
00718   // taken from example in Qt documentation (xml.html)
00719   xmlstream << "<document xmlns:book = \"http://trolltech.com/fnord/book/\"";
00720   xmlstream << "          xmlns      = \"http://trolltech.com/fnord/\" >";
00721   xmlstream << "<book>";
00722   xmlstream << "  <book:title>Practical XML</book:title>";
00723   xmlstream << "  <book:author xmlns:fnord = \"http://trolltech.com/fnord/\"";
00724   xmlstream << "               title=\"Ms\"";
00725   xmlstream << "               fnord:title=\"Goddess\"";
00726   xmlstream << "               name=\"Eris Kallisti\"/>";
00727   xmlstream << "  <chapter>";
00728   xmlstream << "    <title>A Namespace Called fnord</title>";
00729   xmlstream << "  </chapter>";
00730   xmlstream << "</book>";
00731   xmlstream << "</document>";
00732   xmldevice.close();
00733 
00734   KoXmlDocument doc;
00735   KoXmlElement rootElement;
00736   KoXmlElement bookElement;
00737   KoXmlElement bookTitleElement;
00738   KoXmlElement bookAuthorElement;
00739 
00740   // ------------- first without any namespace processing ----------- 
00741   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
00742   CHECK( errorMsg.isEmpty(), true );
00743   CHECK( errorLine, 0 );
00744   CHECK( errorColumn, 0 );
00745 
00746   rootElement = doc.documentElement();
00747   CHECK( rootElement.isNull(), false );
00748   CHECK( rootElement.isElement(), true );
00749   CHECK( rootElement.tagName(), QString("document") );
00750   CHECK( rootElement.prefix().isNull(), true );
00751 
00752   bookElement = rootElement.firstChild().toElement();
00753   CHECK( bookElement.isNull(), false );
00754   CHECK( bookElement.isElement(), true );
00755   CHECK( bookElement.tagName(), QString("book") );
00756   CHECK( bookElement.prefix().isNull(), true );
00757   CHECK( bookElement.localName(), QString() );
00758 
00759   bookTitleElement = bookElement.firstChild().toElement();
00760   CHECK( bookTitleElement.isNull(), false );
00761   CHECK( bookTitleElement.isElement(), true );
00762   CHECK( bookTitleElement.tagName(), QString("book:title") );
00763   CHECK( bookTitleElement.prefix().isNull(), true );
00764   CHECK( bookTitleElement.localName(), QString() );
00765 
00766   bookAuthorElement = bookTitleElement.nextSibling().toElement();
00767   CHECK( bookAuthorElement.isNull(), false );
00768   CHECK( bookAuthorElement.isElement(), true );
00769   CHECK( bookAuthorElement.tagName(), QString("book:author") );
00770   CHECK( bookAuthorElement.prefix().isNull(), true );
00771   CHECK( bookAuthorElement.attribute("title"), QString("Ms") );
00772   CHECK( bookAuthorElement.attribute("fnord:title"), QString("Goddess") );
00773   CHECK( bookAuthorElement.attribute("name"), QString("Eris Kallisti") );
00774 
00775   // ------------- now with namespace processing ----------- 
00776   xmldevice.seek(0); // just to rewind
00777 
00778   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
00779   CHECK( errorMsg.isEmpty(), true );
00780   CHECK( errorLine, 0 );
00781   CHECK( errorColumn, 0 );
00782 
00783   const char* defaultNS = "http://trolltech.com/fnord/";
00784   const char* bookNS = "http://trolltech.com/fnord/book/";
00785   const char* fnordNS = "http://trolltech.com/fnord/";
00786 
00787   // <document>
00788   rootElement = doc.documentElement();
00789   CHECK( rootElement.isNull(), false );
00790   CHECK( rootElement.isElement(), true );
00791   CHECK( rootElement.tagName(), QString("document") );
00792   CHECK( rootElement.prefix().isEmpty(), true );
00793   CHECK( rootElement.namespaceURI(), QString( defaultNS ) );
00794   CHECK( rootElement.localName(), QString("document") );
00795 
00796   // <book>
00797   bookElement = rootElement.firstChild().toElement();
00798   CHECK( bookElement.isNull(), false );
00799   CHECK( bookElement.isElement(), true );
00800   CHECK( bookElement.tagName(), QString("book") );
00801   CHECK( bookElement.prefix().isEmpty(), true );
00802   CHECK( bookElement.namespaceURI(), QString( defaultNS ) );
00803   CHECK( bookElement.localName(), QString("book") );
00804 
00805   // <book:title>
00806   bookTitleElement = bookElement.firstChild().toElement();
00807   CHECK( bookTitleElement.isNull(), false );
00808   CHECK( bookTitleElement.isElement(), true );
00809   CHECK( bookTitleElement.tagName(), QString("title") );
00810   CHECK( bookTitleElement.prefix(), QString("book") );
00811   CHECK( bookTitleElement.namespaceURI(), QString(bookNS) );
00812   CHECK( bookTitleElement.localName(), QString("title") );
00813 
00814   // another way, find it using namedItemNS()
00815   KoXmlElement book2TitleElement;
00816   book2TitleElement = KoXml::namedItemNS( rootElement.firstChild(), bookNS, "title" );
00817   //book2TitleElement = bookElement.namedItemNS( bookNS, "title" ).toElement();
00818   CHECK( book2TitleElement==bookTitleElement, true );
00819   CHECK( book2TitleElement.isNull(), false );
00820   CHECK( book2TitleElement.isElement(), true );
00821   CHECK( book2TitleElement.tagName(), QString("title") );
00822 
00823   // <book:author>
00824   bookAuthorElement = bookTitleElement.nextSibling().toElement();
00825   CHECK( bookAuthorElement.isNull(), false );
00826   CHECK( bookAuthorElement.isElement(), true );
00827   CHECK( bookAuthorElement.tagName(), QString("author") );
00828   CHECK( bookAuthorElement.prefix(), QString("book") );
00829   CHECK( bookAuthorElement.namespaceURI(), QString(bookNS) );
00830   CHECK( bookAuthorElement.localName(), QString("author") );
00831 
00832   // another way, find it using namedItemNS()
00833   KoXmlElement book2AuthorElement;
00834   book2AuthorElement = KoXml::namedItemNS( bookElement, bookNS, "author" );
00835   //book2AuthorElement = bookElement.namedItemNS( bookNS, "author" ).toElement();
00836   CHECK( book2AuthorElement==bookAuthorElement, true );
00837   CHECK( book2AuthorElement.isNull(), false );
00838   CHECK( book2AuthorElement.isElement(), true );
00839   CHECK( book2AuthorElement.tagName(), QString("author") );
00840 
00841   // attributes in <book:author>
00842   // Note: with namespace processing, attribute's prefix is taken out and
00843   // hence "fnord:title" will simply override "title"
00844   // and searching attribute with prefix will give no result
00845   CHECK( bookAuthorElement.hasAttribute("title"), true );
00846   CHECK( bookAuthorElement.hasAttribute("fnord:title"), false );
00847   CHECK( bookAuthorElement.hasAttribute("name"), true );
00848   CHECK( bookAuthorElement.attribute("title"), QString("Goddess") );
00849   CHECK( bookAuthorElement.attribute("fnord:title").isEmpty(), true );
00850   CHECK( bookAuthorElement.attribute("name"), QString("Eris Kallisti") );
00851 
00852   // attributes in <book:author>, with NS family of functions
00853   // those without prefix are not accessible at all, because they do not belong
00854   // to any namespace at all.
00855   // Note: default namespace does not apply to attribute names!
00856   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"title"), true );
00857   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"title"), false );
00858   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"title"), true );
00859 
00860   CHECK( bookAuthorElement.attributeNS(defaultNS,"title",""), QString("Goddess") );
00861   CHECK( bookAuthorElement.attributeNS(bookNS,"title",""), QString("") );
00862   CHECK( bookAuthorElement.attributeNS(fnordNS,"title",""), QString("Goddess") );
00863 
00864   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"fnord:title"), false );
00865   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"fnord:title"), false );
00866   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"fnord:title"), false );
00867   
00868   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"name"), false );
00869   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"name"), false );
00870   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"name"), false );
00871   
00872   CHECK( bookAuthorElement.attributeNS(defaultNS,"name",QString()).isEmpty(), true );
00873   CHECK( bookAuthorElement.attributeNS(bookNS,"name",QString()).isEmpty(), true );
00874   CHECK( bookAuthorElement.attributeNS(fnordNS,"name",QString()).isEmpty(), true );
00875 }
00876 
00877 // mostly similar to testNamespace above, but parse from a QString
00878 void testParseQString()
00879 {
00880   QString errorMsg;
00881   int errorLine = 0;
00882   int errorColumn = 0;
00883 
00884   QString xmlText;
00885   xmlText +=  "<document xmlns:book = \"http://trolltech.com/fnord/book/\"";
00886   xmlText +=  "          xmlns      = \"http://trolltech.com/fnord/\" >";
00887   xmlText +=  "<book>";
00888   xmlText +=  "  <book:title>Practical XML</book:title>";
00889   xmlText +=  "  <book:author xmlns:fnord = \"http://trolltech.com/fnord/\"";
00890   xmlText +=  "               title=\"Ms\"";
00891   xmlText +=  "               fnord:title=\"Goddess\"";
00892   xmlText +=  "               name=\"Eris Kallisti\"/>";
00893   xmlText +=  "  <chapter>";
00894   xmlText +=  "    <title>A Namespace Called fnord</title>";
00895   xmlText +=  "  </chapter>";
00896   xmlText +=  "</book>";
00897   xmlText +=  "</document>";
00898 
00899   KoXmlDocument doc;
00900   KoXmlElement rootElement;
00901   KoXmlElement bookElement;
00902   KoXmlElement bookTitleElement;
00903   KoXmlElement bookAuthorElement;
00904 
00905   CHECK( doc.setContent( xmlText, true, &errorMsg, &errorLine, &errorColumn ), true );
00906   CHECK( errorMsg.isEmpty(), true );
00907   CHECK( errorLine, 0 );
00908   CHECK( errorColumn, 0 );
00909 
00910   const char* defaultNS = "http://trolltech.com/fnord/";
00911   const char* bookNS = "http://trolltech.com/fnord/book/";
00912   const char* fnordNS = "http://trolltech.com/fnord/";
00913 
00914   // <document>
00915   rootElement = doc.documentElement();
00916   CHECK( rootElement.isNull(), false );
00917   CHECK( rootElement.isElement(), true );
00918   CHECK( rootElement.tagName(), QString("document") );
00919   CHECK( rootElement.prefix().isEmpty(), true );
00920   CHECK( rootElement.namespaceURI(), QString( defaultNS ) );
00921   CHECK( rootElement.localName(), QString("document") );
00922 
00923   // <book>
00924   bookElement = rootElement.firstChild().toElement();
00925   CHECK( bookElement.isNull(), false );
00926   CHECK( bookElement.isElement(), true );
00927   CHECK( bookElement.tagName(), QString("book") );
00928   CHECK( bookElement.prefix().isEmpty(), true );
00929   CHECK( bookElement.namespaceURI(), QString( defaultNS ) );
00930   CHECK( bookElement.localName(), QString("book") );
00931 
00932   // <book:title>
00933   bookTitleElement = bookElement.firstChild().toElement();
00934   CHECK( bookTitleElement.isNull(), false );
00935   CHECK( bookTitleElement.isElement(), true );
00936   CHECK( bookTitleElement.tagName(), QString("title") );
00937   CHECK( bookTitleElement.prefix(), QString("book") );
00938   CHECK( bookTitleElement.namespaceURI(), QString(bookNS) );
00939   CHECK( bookTitleElement.localName(), QString("title") );
00940 
00941   // another way, find it using namedItemNS()
00942   KoXmlElement book2TitleElement;
00943   book2TitleElement = KoXml::namedItemNS( rootElement.firstChild(), bookNS, "title" );
00944   //book2TitleElement = bookElement.namedItemNS( bookNS, "title" ).toElement();
00945   CHECK( book2TitleElement==bookTitleElement, true );
00946   CHECK( book2TitleElement.isNull(), false );
00947   CHECK( book2TitleElement.isElement(), true );
00948   CHECK( book2TitleElement.tagName(), QString("title") );
00949 
00950   // <book:author>
00951   bookAuthorElement = bookTitleElement.nextSibling().toElement();
00952   CHECK( bookAuthorElement.isNull(), false );
00953   CHECK( bookAuthorElement.isElement(), true );
00954   CHECK( bookAuthorElement.tagName(), QString("author") );
00955   CHECK( bookAuthorElement.prefix(), QString("book") );
00956   CHECK( bookAuthorElement.namespaceURI(), QString(bookNS) );
00957   CHECK( bookAuthorElement.localName(), QString("author") );
00958 
00959   // another way, find it using namedItemNS()
00960   KoXmlElement book2AuthorElement;
00961   book2AuthorElement = KoXml::namedItemNS( bookElement, bookNS, "author" );
00962   //book2AuthorElement = bookElement.namedItemNS( bookNS, "author" ).toElement();
00963   CHECK( book2AuthorElement==bookAuthorElement, true );
00964   CHECK( book2AuthorElement.isNull(), false );
00965   CHECK( book2AuthorElement.isElement(), true );
00966   CHECK( book2AuthorElement.tagName(), QString("author") );
00967 
00968   // attributes in <book:author>
00969   // Note: with namespace processing, attribute's prefix is taken out and
00970   // hence "fnord:title" will simply override "title"
00971   // and searching attribute with prefix will give no result
00972   CHECK( bookAuthorElement.hasAttribute("title"), true );
00973   CHECK( bookAuthorElement.hasAttribute("fnord:title"), false );
00974   CHECK( bookAuthorElement.hasAttribute("name"), true );
00975   CHECK( bookAuthorElement.attribute("title"), QString("Goddess") );
00976   CHECK( bookAuthorElement.attribute("fnord:title").isEmpty(), true );
00977   CHECK( bookAuthorElement.attribute("name"), QString("Eris Kallisti") );
00978 
00979   // attributes in <book:author>, with NS family of functions
00980   // those without prefix are not accessible at all, because they do not belong
00981   // to any namespace at all.
00982   // Note: default namespace does not apply to attribute names!
00983   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"title"), true );
00984   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"title"), false );
00985   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"title"), true );
00986 
00987   CHECK( bookAuthorElement.attributeNS(defaultNS,"title",""), QString("Goddess") );
00988   CHECK( bookAuthorElement.attributeNS(bookNS,"title",""), QString("") );
00989   CHECK( bookAuthorElement.attributeNS(fnordNS,"title",""), QString("Goddess") );
00990 
00991   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"fnord:title"), false );
00992   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"fnord:title"), false );
00993   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"fnord:title"), false );
00994   
00995   CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"name"), false );
00996   CHECK( bookAuthorElement.hasAttributeNS(bookNS,"name"), false );
00997   CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"name"), false );
00998   
00999   CHECK( bookAuthorElement.attributeNS(defaultNS,"name",QString()).isEmpty(), true );
01000   CHECK( bookAuthorElement.attributeNS(bookNS,"name",QString()).isEmpty(), true );
01001   CHECK( bookAuthorElement.attributeNS(fnordNS,"name",QString()).isEmpty(), true );
01002 }
01003 
01004 void testUnload()
01005 {
01006   QString errorMsg;
01007   int errorLine = 0;
01008   int errorColumn = 0;
01009 
01010   QBuffer xmldevice;
01011   xmldevice.open( QIODevice::WriteOnly );
01012   QTextStream xmlstream( &xmldevice );
01013   
01014   xmlstream << "<earth>";
01015   xmlstream << "<continents>";
01016   xmlstream << "<asia/>";
01017   xmlstream << "<africa/>";
01018   xmlstream << "<europe/>";
01019   xmlstream << "<america/>";
01020   xmlstream << "<australia/>";
01021   xmlstream << "<antartic/>";
01022   xmlstream << "</continents>";
01023   xmlstream << "<oceans>";
01024   xmlstream << "<pacific/>";
01025   xmlstream << "<atlantic/>";
01026   xmlstream << "</oceans>";
01027   xmlstream << "</earth>";
01028   xmldevice.close();
01029 
01030   KoXmlDocument doc;
01031   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
01032   CHECK( errorMsg.isEmpty(), true );
01033   CHECK( errorLine, 0 );
01034   CHECK( errorColumn, 0 );
01035 
01036   KoXmlElement earthElement;
01037   earthElement = doc.documentElement().toElement();
01038   CHECK( earthElement.isNull(), false );
01039   CHECK( earthElement.isElement(), true );
01040   CHECK( earthElement.parentNode().isNull(), false );
01041   CHECK( earthElement.hasChildNodes(), true );
01042   CHECK( KoXml::childNodesCount(earthElement), 2 );
01043   CHECK( earthElement.tagName(), QString("earth") );
01044   CHECK( earthElement.prefix().isNull(), true );
01045 
01046   // this ensures that all child nodes of <earth> are loaded
01047   earthElement.firstChild();
01048 
01049   // explicitly unload all child nodes of <earth>
01050   KoXml::unload( earthElement );
01051 
01052   // we should get the correct first child
01053   KoXmlElement continentsElement = earthElement.firstChild().toElement();
01054   CHECK( continentsElement.nodeName(), QString("continents") );
01055   CHECK( continentsElement.isNull(), false );
01056   CHECK( continentsElement.isElement(), true );
01057   CHECK( continentsElement.isText(), false );
01058   CHECK( continentsElement.isDocument(), false );
01059   CHECK( continentsElement.hasChildNodes(), true );
01060   CHECK( KoXml::childNodesCount(continentsElement), 6 );
01061   
01062   // let us unload everything again
01063   KoXml::unload( earthElement );
01064 
01065   // we should get the correct last child
01066   KoXmlElement oceansElement = earthElement.lastChild().toElement();
01067   CHECK( oceansElement.nodeName(), QString("oceans") );
01068   CHECK( oceansElement.isNull(), false );
01069   CHECK( oceansElement.isElement(), true );
01070   CHECK( oceansElement.isText(), false );
01071   CHECK( oceansElement.isDocument(), false );
01072   CHECK( oceansElement.hasChildNodes(), true );
01073   CHECK( KoXml::childNodesCount(continentsElement), 6 );
01074 }
01075 
01076 void testSimpleXML()
01077 {
01078   QString errorMsg;
01079   int errorLine = 0;
01080   int errorColumn = 0;
01081 
01082   QBuffer xmldevice;
01083   xmldevice.open( QIODevice::WriteOnly );
01084   QTextStream xmlstream( &xmldevice );
01085   xmlstream << "<solarsystem>";
01086   xmlstream << "  <mercurius/>\n";
01087   xmlstream << "  <venus/>\n";
01088   xmlstream << "  <earth>\n";
01089   xmlstream << "    <moon/>\n";
01090   xmlstream << "  </earth>\n";
01091   xmlstream << "  <mars/>\n";
01092   xmlstream << "  <jupiter/>\n";
01093   xmlstream << "</solarsystem>";
01094   xmldevice.close();
01095 
01096   KoXmlDocument doc;
01097   CHECK( doc.setContent(&xmldevice,&errorMsg,&errorLine,&errorColumn ), true );
01098   CHECK( errorMsg.isEmpty(), true );
01099   CHECK( errorLine, 0 );
01100   CHECK( errorColumn, 0 );
01101 
01102   // <solarsystem>
01103   KoXmlElement rootElement;
01104   rootElement = doc.documentElement();
01105   CHECK( rootElement.isNull(), false );
01106   CHECK( rootElement.isElement(), true );
01107   CHECK( rootElement.parentNode().isNull(), false );
01108   CHECK( rootElement.hasChildNodes(), true );
01109   CHECK( KoXml::childNodesCount(rootElement), 5 );
01110   CHECK( rootElement.tagName(), QString("solarsystem") );
01111   CHECK( rootElement.prefix().isNull(), true );
01112 
01113   // node <mercurius>
01114   KoXmlNode firstPlanetNode;
01115   firstPlanetNode = rootElement.firstChild();
01116   CHECK( firstPlanetNode.isNull(), false );
01117   CHECK( firstPlanetNode.isElement(), true );
01118   CHECK( firstPlanetNode.nextSibling().isNull(), false );
01119   CHECK( firstPlanetNode.previousSibling().isNull(), true );
01120   CHECK( firstPlanetNode.parentNode().isNull(), false );
01121   CHECK( firstPlanetNode.parentNode()==rootElement, true );
01122   CHECK( firstPlanetNode.parentNode()!=rootElement, false );
01123   CHECK( firstPlanetNode.hasChildNodes(), false );
01124   CHECK( KoXml::childNodesCount(firstPlanetNode), 0 );
01125   CHECK( firstPlanetNode.firstChild().isNull(), true );
01126   CHECK( firstPlanetNode.lastChild().isNull(), true );
01127 
01128   // element <mercurius>
01129   KoXmlElement firstPlanetElement;
01130   firstPlanetElement = firstPlanetNode.toElement();
01131   CHECK( firstPlanetElement.isNull(), false );
01132   CHECK( firstPlanetElement.isElement(), true );
01133   CHECK( firstPlanetElement.parentNode().isNull(), false );
01134   CHECK( firstPlanetElement.parentNode()==rootElement, true );
01135   CHECK( firstPlanetElement.hasChildNodes(), false );
01136   CHECK( KoXml::childNodesCount(firstPlanetNode), 0 );
01137   CHECK( firstPlanetElement.firstChild().isNull(), true );
01138   CHECK( firstPlanetElement.lastChild().isNull(), true );
01139   CHECK( firstPlanetElement.tagName(), QString("mercurius") );
01140   CHECK( firstPlanetElement.prefix().isNull(), true );
01141 
01142   // node <venus>
01143   KoXmlNode secondPlanetNode;
01144   secondPlanetNode = firstPlanetNode.nextSibling();
01145   CHECK( secondPlanetNode.isNull(), false );
01146   CHECK( secondPlanetNode.isElement(), true );
01147   CHECK( secondPlanetNode.nextSibling().isNull(), false );
01148   CHECK( secondPlanetNode.previousSibling().isNull(), false );
01149   CHECK( secondPlanetNode.previousSibling()==firstPlanetNode, true );
01150   CHECK( secondPlanetNode.previousSibling()==firstPlanetElement, true );
01151   CHECK( secondPlanetNode.parentNode().isNull(), false );
01152   CHECK( secondPlanetNode.parentNode()==rootElement, true );
01153   CHECK( secondPlanetNode.parentNode()!=rootElement, false );
01154   CHECK( secondPlanetNode.hasChildNodes(), false );
01155   CHECK( KoXml::childNodesCount(secondPlanetNode), 0 );
01156   CHECK( secondPlanetNode.firstChild().isNull(), true );
01157   CHECK( secondPlanetNode.lastChild().isNull(), true );
01158 
01159   // element <venus>
01160   KoXmlElement secondPlanetElement;
01161   secondPlanetElement = secondPlanetNode.toElement();
01162   CHECK( secondPlanetElement.isNull(), false );
01163   CHECK( secondPlanetElement.isElement(), true );
01164   CHECK( secondPlanetElement.nextSibling().isNull(), false );
01165   CHECK( secondPlanetElement.previousSibling().isNull(), false );
01166   CHECK( secondPlanetElement.previousSibling()==firstPlanetNode, true );
01167   CHECK( secondPlanetElement.previousSibling()==firstPlanetElement, true );
01168   CHECK( secondPlanetElement.parentNode().isNull(), false );
01169   CHECK( secondPlanetElement.parentNode()==rootElement, true );
01170   CHECK( secondPlanetElement.parentNode()!=rootElement, false );
01171   CHECK( secondPlanetElement.hasChildNodes(), false );
01172   CHECK( KoXml::childNodesCount(secondPlanetNode), 0 );
01173   CHECK( secondPlanetElement.firstChild().isNull(), true );
01174   CHECK( secondPlanetElement.lastChild().isNull(), true );
01175   CHECK( secondPlanetElement.tagName(), QString("venus") );
01176   CHECK( secondPlanetElement.prefix().isNull(), true );
01177 }
01178 
01179 void testRootError()
01180 {
01181   QString errorMsg;
01182   int errorLine = 0;
01183   int errorColumn = 0;
01184 
01185   // multiple root nodes are not valid !
01186   QBuffer xmldevice;
01187   xmldevice.open( QIODevice::WriteOnly );
01188   QTextStream xmlstream( &xmldevice );
01189   xmlstream << "<earth></earth><moon></moon>";
01190   xmldevice.close();
01191 
01192   KoXmlDocument doc;
01193   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), false );
01194   CHECK( errorMsg.isEmpty(), false );
01195   CHECK( errorMsg, QString("unexpected character") );
01196   CHECK( errorLine, 1 );
01197   CHECK( errorColumn, 17 );
01198 }
01199 
01200 void testMismatchedTag()
01201 {
01202   QString errorMsg;
01203   int errorLine = 0;
01204   int errorColumn = 0;
01205 
01206   QBuffer xmldevice;
01207   xmldevice.open( QIODevice::WriteOnly );
01208   QTextStream xmlstream( &xmldevice );
01209   xmlstream << "<earth></e>";
01210   xmldevice.close();
01211 
01212   KoXmlDocument doc;
01213   CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), false );
01214   CHECK( errorMsg.isEmpty(), false );
01215   CHECK( errorMsg, QString("tag mismatch") );
01216   CHECK( errorLine, 1 );
01217   CHECK( errorColumn, 11 );
01218 }
01219 
01220 void testConvertQDomElement()
01221 {
01222   QString errorMsg;
01223   int errorLine = 0;
01224   int errorColumn = 0;
01225 
01226   QBuffer xmldevice;
01227   xmldevice.open( QIODevice::WriteOnly );
01228   QTextStream xmlstream( &xmldevice );
01229   xmlstream << "<solarsystem star=\"sun\">";
01230   xmlstream << "  <mercurius/>\n";
01231   xmlstream << "  <venus/>\n";
01232   xmlstream << "  <earth habitable=\"true\"><p>The best place</p>";
01233   xmlstream << "    <moon  habitable=\"possible\"/>\n";
01234   xmlstream << "  </earth>\n";
01235   xmlstream << "  <mars/>\n";
01236   xmlstream << "  <jupiter/>\n";
01237   xmlstream << "</solarsystem>";
01238   xmldevice.close();
01239 
01240   KoXmlDocument doc;
01241   CHECK( doc.setContent(&xmldevice,&errorMsg,&errorLine,&errorColumn ), true );
01242   CHECK( errorMsg.isEmpty(), true );
01243   CHECK( errorLine, 0 );
01244   CHECK( errorColumn, 0 );
01245   
01246   // <solarsystem>
01247   KoXmlElement rootElement;
01248   rootElement = doc.documentElement();
01249   CHECK( rootElement.isNull(), false );
01250   CHECK( rootElement.isElement(), true );
01251   CHECK( rootElement.parentNode().isNull(), false );
01252   CHECK( rootElement.hasChildNodes(), true );
01253   CHECK( KoXml::childNodesCount(rootElement), 5 );
01254   CHECK( rootElement.tagName(), QString("solarsystem") );
01255   CHECK( rootElement.prefix().isNull(), true );
01256 
01257   // now test converting KoXmlElement to QDomElement
01258   QDomDocument universeDoc;
01259   QDomElement universeRoot = universeDoc.createElement("universe");
01260   universeDoc.appendChild( universeRoot );
01261   universeRoot.appendChild( KoXml::asQDomNode( universeDoc, rootElement ) );
01262   
01263   // <solarsystem>
01264   QDomElement solarSystemElement = universeRoot.firstChild().toElement();
01265   CHECK( solarSystemElement.isNull(), false );
01266   CHECK( solarSystemElement.isElement(), true );
01267   CHECK( solarSystemElement.parentNode().isNull(), false );
01268   CHECK( solarSystemElement.hasChildNodes(), true );
01269   CHECK( solarSystemElement.tagName(), QString("solarsystem") );
01270   CHECK( solarSystemElement.prefix().isNull(), true );
01271   
01272   // <earth>
01273   QDomElement earthElement = solarSystemElement.namedItem("earth").toElement();
01274   CHECK( earthElement.isNull(), false );
01275   CHECK( earthElement.isElement(), true );
01276   CHECK( earthElement.parentNode().isNull(), false );
01277   CHECK( earthElement.hasAttribute("habitable"), true );
01278   CHECK( earthElement.hasChildNodes(), true );
01279   CHECK( earthElement.tagName(), QString("earth") );
01280   CHECK( earthElement.prefix().isNull(), true );
01281   
01282   // <p> in <earth>
01283   QDomNode placeNode = earthElement.firstChild();
01284   CHECK( placeNode.isNull(), false );
01285   CHECK( placeNode.isElement(), true );
01286   CHECK( placeNode.toElement().text(), QString("The best place") );
01287   CHECK( placeNode.nextSibling().isNull(), false );
01288   CHECK( placeNode.previousSibling().isNull(), true );
01289   CHECK( placeNode.parentNode().isNull(), false );
01290   CHECK( placeNode.parentNode()==earthElement, true );
01291   CHECK( placeNode.hasChildNodes(), true );
01292   CHECK( placeNode.childNodes().count(), 1 );
01293   
01294   //printf("Result:\n%s\n\n", qPrintable(universeDoc.toString()));
01295 }
01296 
01297 void testSimpleOpenDocumentText()
01298 {
01299   QString errorMsg;
01300   int errorLine = 0;
01301   int errorColumn = 0;
01302 
01303   QBuffer xmldevice;
01304   xmldevice.open( QIODevice::WriteOnly );
01305   QTextStream xmlstream( &xmldevice );
01306   
01307   // content.xml from a simple OpenDocument text
01308   // it has only paragraph "Hello, world!"
01309   // automatic styles, declarations and unnecessary namespaces are omitted.
01310   xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
01311   xmlstream << "<office:document-content ";
01312   xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
01313   xmlstream << " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"";
01314   xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
01315   xmlstream << "   office:version=\"1.0\">";
01316   xmlstream << " <office:automatic-styles/>";
01317   xmlstream << " <office:body>";
01318   xmlstream << "  <office:text>";
01319   xmlstream << "   <text:p text:style-name=\"Standard\">Hello, world!</text:p>";
01320   xmlstream << "  </office:text>";
01321   xmlstream << " </office:body>";
01322   xmlstream << "</office:document-content>";
01323   xmldevice.close();
01324 
01325   KoXmlDocument doc;
01326   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
01327   CHECK( errorMsg.isEmpty(), true );
01328   CHECK( errorLine, 0 );
01329   CHECK( errorColumn, 0 );
01330 
01331   const char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; 
01332   const char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
01333 
01334   // <office:document-content>
01335   KoXmlElement contentElement;
01336   contentElement = doc.documentElement();
01337   CHECK( contentElement.isNull(), false );
01338   CHECK( contentElement.isElement(), true );
01339   CHECK( contentElement.parentNode().isNull(), false );
01340   CHECK( contentElement.parentNode().toDocument()==doc, true );
01341   CHECK( KoXml::childNodesCount(contentElement), 2 );
01342   CHECK( contentElement.firstChild().isNull(), false );
01343   CHECK( contentElement.lastChild().isNull(), false );
01344   CHECK( contentElement.previousSibling().isNull(), false );
01345   CHECK( contentElement.nextSibling().isNull(), true );
01346   CHECK( contentElement.localName(), QString("document-content") );
01347   CHECK( contentElement.hasAttributeNS(officeNS,"version"), true );
01348   CHECK( contentElement.attributeNS(officeNS,"version",""), QString("1.0") );
01349   
01350   // <office:automatic-styles>
01351   KoXmlElement stylesElement;
01352   stylesElement = KoXml::namedItemNS( contentElement, officeNS, "automatic-styles" );
01353   CHECK( stylesElement.isNull(), false );
01354   CHECK( stylesElement.isElement(), true );
01355   CHECK( stylesElement.parentNode().isNull(), false );
01356   CHECK( stylesElement.parentNode()==contentElement, true );
01357   CHECK( KoXml::childNodesCount(stylesElement), 0 );
01358   CHECK( stylesElement.firstChild().isNull(), true );
01359   CHECK( stylesElement.lastChild().isNull(), true );
01360   CHECK( stylesElement.previousSibling().isNull(), true );
01361   CHECK( stylesElement.nextSibling().isNull(), false );
01362   CHECK( stylesElement.localName(), QString("automatic-styles") );
01363   
01364   // also same <office:automatic-styles>, but without namedItemNS
01365   KoXmlNode styles2Element;
01366   styles2Element = contentElement.firstChild().toElement();
01367   CHECK( styles2Element.isNull(), false );
01368   CHECK( styles2Element.isElement(), true );
01369   CHECK( styles2Element.parentNode().isNull(), false );
01370   CHECK( styles2Element.parentNode()==contentElement, true );
01371   CHECK( KoXml::childNodesCount(styles2Element), 0 );
01372   CHECK( styles2Element.firstChild().isNull(), true );
01373   CHECK( styles2Element.lastChild().isNull(), true );
01374   CHECK( styles2Element.previousSibling().isNull(), true );
01375   CHECK( styles2Element.nextSibling().isNull(), false );
01376   CHECK( styles2Element.localName(), QString("automatic-styles") );
01377 
01378   // <office:body>
01379   KoXmlElement bodyElement;
01380   bodyElement = KoXml::namedItemNS( contentElement, officeNS, "body" );
01381   CHECK( bodyElement.isNull(), false );
01382   CHECK( bodyElement.isElement(), true );
01383   CHECK( bodyElement.parentNode().isNull(), false );
01384   CHECK( bodyElement.parentNode()==contentElement, true );
01385   CHECK( KoXml::childNodesCount(bodyElement), 1 );
01386   CHECK( bodyElement.firstChild().isNull(), false );
01387   CHECK( bodyElement.lastChild().isNull(), false );
01388   CHECK( bodyElement.previousSibling().isNull(), false );
01389   CHECK( bodyElement.nextSibling().isNull(), true );
01390   CHECK( bodyElement.localName(), QString("body") );
01391 
01392   // also same <office:body>, but without namedItemNS
01393   KoXmlElement body2Element;
01394   body2Element = stylesElement.nextSibling().toElement();
01395   CHECK( body2Element.isNull(), false );
01396   CHECK( body2Element.isElement(), true );
01397   CHECK( body2Element.parentNode().isNull(), false );
01398   CHECK( body2Element.parentNode()==contentElement, true );
01399   CHECK( KoXml::childNodesCount(body2Element), 1 );
01400   CHECK( body2Element.firstChild().isNull(), false );
01401   CHECK( body2Element.lastChild().isNull(), false );
01402   CHECK( body2Element.previousSibling().isNull(), false );
01403   CHECK( body2Element.nextSibling().isNull(), true );
01404   CHECK( body2Element.localName(), QString("body") );
01405 
01406   // <office:text>
01407   KoXmlElement textElement;
01408   textElement = KoXml::namedItemNS( bodyElement, officeNS, "text" );
01409   CHECK( textElement.isNull(), false );
01410   CHECK( textElement.isElement(), true );
01411   CHECK( textElement.parentNode().isNull(), false );
01412   CHECK( textElement.parentNode()==bodyElement, true );
01413   CHECK( KoXml::childNodesCount(textElement), 1 );
01414   CHECK( textElement.firstChild().isNull(), false );
01415   CHECK( textElement.lastChild().isNull(), false );
01416   CHECK( textElement.previousSibling().isNull(), true );
01417   CHECK( textElement.nextSibling().isNull(), true );
01418   CHECK( textElement.localName(), QString("text") );
01419 
01420   // the same <office:text>, but without namedItemNS
01421   KoXmlElement text2Element;
01422   text2Element = bodyElement.firstChild().toElement();
01423   CHECK( text2Element.isNull(), false );
01424   CHECK( text2Element.isElement(), true );
01425   CHECK( text2Element.parentNode().isNull(), false );
01426   CHECK( text2Element.parentNode()==bodyElement, true );
01427   CHECK( KoXml::childNodesCount(text2Element), 1 );
01428   CHECK( text2Element.firstChild().isNull(), false );
01429   CHECK( text2Element.lastChild().isNull(), false );
01430   CHECK( text2Element.previousSibling().isNull(), true );
01431   CHECK( text2Element.nextSibling().isNull(), true );
01432   CHECK( text2Element.localName(), QString("text") );
01433 
01434   // <text:p>
01435   KoXmlElement parElement;
01436   parElement = textElement.firstChild().toElement();
01437   CHECK( parElement.isNull(), false );
01438   CHECK( parElement.isElement(), true );
01439   CHECK( parElement.parentNode().isNull(), false );
01440   CHECK( parElement.parentNode()==textElement, true );
01441   CHECK( KoXml::childNodesCount(parElement), 1 );
01442   CHECK( parElement.firstChild().isNull(), false );
01443   CHECK( parElement.lastChild().isNull(), false );
01444   CHECK( parElement.previousSibling().isNull(), true );
01445   CHECK( parElement.nextSibling().isNull(), true );
01446   CHECK( parElement.tagName(), QString("p") );
01447   CHECK( parElement.text(), QString("Hello, world!") );
01448   CHECK( parElement.attributeNS( QString(textNS),"style-name",""), QString("Standard") );
01449 }
01450 
01451 void testSimpleOpenDocumentSpreadsheet()
01452 {
01453   QString errorMsg;
01454   int errorLine = 0;
01455   int errorColumn = 0;
01456 
01457   QBuffer xmldevice;
01458   xmldevice.open( QIODevice::WriteOnly );
01459   QTextStream xmlstream( &xmldevice );
01460   
01461   // content.xml from a simple OpenDocument spreadsheet
01462   // the document has three worksheets, the last two are empty.
01463   // on the first sheet, cell A1 contains the text "Hello, world".
01464   // automatic styles, font declarations and unnecessary namespaces are omitted.
01465 
01466   xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
01467   xmlstream << "<office:document-content ";
01468   xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
01469   xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
01470   xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\">";
01471   xmlstream << "<office:body>";
01472   xmlstream << "<office:spreadsheet>";
01473   xmlstream << "<table:table table:name=\"Sheet1\" table:style-name=\"ta1\" table:print=\"false\">";
01474   xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
01475   xmlstream << "<table:table-row table:style-name=\"ro1\">";
01476   xmlstream << "<table:table-cell office:value-type=\"string\">";
01477   xmlstream << "<text:p>Hello, world</text:p>";
01478   xmlstream << "</table:table-cell>";
01479   xmlstream << "</table:table-row>";
01480   xmlstream << "</table:table>";
01481   xmlstream << "<table:table table:name=\"Sheet2\" table:style-name=\"ta1\" table:print=\"false\">";
01482   xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
01483   xmlstream << "<table:table-row table:style-name=\"ro1\">";
01484   xmlstream << "<table:table-cell/>";
01485   xmlstream << "</table:table-row>";
01486   xmlstream << "</table:table>";
01487   xmlstream << "<table:table table:name=\"Sheet3\" table:style-name=\"ta1\" table:print=\"false\">";
01488   xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
01489   xmlstream << "<table:table-row table:style-name=\"ro1\">";
01490   xmlstream << "<table:table-cell/>";
01491   xmlstream << "</table:table-row>";
01492   xmlstream << "</table:table>";
01493   xmlstream << "</office:spreadsheet>";
01494   xmlstream << "</office:body>";
01495   xmlstream << "</office:document-content>";
01496   xmldevice.close();
01497 
01498   KoXmlDocument doc;
01499   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
01500   CHECK( errorMsg.isEmpty(), true );
01501   CHECK( errorLine, 0 );
01502   CHECK( errorColumn, 0 );
01503   
01504   QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; 
01505   QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
01506   QString textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
01507 
01508   // <office:document-content>
01509   KoXmlElement contentElement;
01510   contentElement = doc.documentElement();
01511   CHECK( contentElement.isNull(), false );
01512   CHECK( contentElement.isElement(), true );
01513   CHECK( contentElement.parentNode().isNull(), false );
01514   CHECK( contentElement.parentNode().toDocument()==doc, true );
01515   CHECK( KoXml::childNodesCount(contentElement), 1 );
01516   CHECK( contentElement.firstChild().isNull(), false );
01517   CHECK( contentElement.lastChild().isNull(), false );
01518   CHECK( contentElement.previousSibling().isNull(), false );
01519   CHECK( contentElement.nextSibling().isNull(), true );
01520   CHECK( contentElement.localName(), QString("document-content") );
01521   
01522   // <office:body>
01523   KoXmlElement bodyElement;
01524   bodyElement = contentElement.firstChild().toElement();
01525   CHECK( bodyElement.isNull(), false );
01526   CHECK( bodyElement.isElement(), true );
01527   CHECK( bodyElement.parentNode().isNull(), false );
01528   CHECK( bodyElement.parentNode()==contentElement, true );
01529   CHECK( KoXml::childNodesCount(bodyElement), 1 );
01530   CHECK( bodyElement.firstChild().isNull(), false );
01531   CHECK( bodyElement.lastChild().isNull(), false );
01532   CHECK( bodyElement.previousSibling().isNull(), true );
01533   CHECK( bodyElement.nextSibling().isNull(), true );
01534   CHECK( bodyElement.localName(), QString("body") );
01535 
01536   // <office:spreadsheet>
01537   KoXmlElement spreadsheetElement;
01538   spreadsheetElement = bodyElement.firstChild().toElement();
01539   CHECK( spreadsheetElement.isNull(), false );
01540   CHECK( spreadsheetElement.isElement(), true );
01541   CHECK( spreadsheetElement.parentNode().isNull(), false );
01542   CHECK( spreadsheetElement.parentNode()==bodyElement, true );
01543   CHECK( KoXml::childNodesCount(spreadsheetElement), 3 );
01544   CHECK( spreadsheetElement.firstChild().isNull(), false );
01545   CHECK( spreadsheetElement.lastChild().isNull(), false );
01546   CHECK( spreadsheetElement.previousSibling().isNull(), true );
01547   CHECK( spreadsheetElement.nextSibling().isNull(), true );
01548   CHECK( spreadsheetElement.localName(), QString("spreadsheet") );
01549   
01550   // <table:table> for Sheet1
01551   KoXmlElement sheet1Element;
01552   sheet1Element = spreadsheetElement.firstChild().toElement();
01553   CHECK( sheet1Element.isNull(), false );
01554   CHECK( sheet1Element.isElement(), true );
01555   CHECK( sheet1Element.parentNode().isNull(), false );
01556   CHECK( sheet1Element.parentNode()==spreadsheetElement, true );
01557   CHECK( KoXml::childNodesCount(sheet1Element), 2 );
01558   CHECK( sheet1Element.firstChild().isNull(), false );
01559   CHECK( sheet1Element.lastChild().isNull(), false );
01560   CHECK( sheet1Element.previousSibling().isNull(), true );
01561   CHECK( sheet1Element.nextSibling().isNull(), false );
01562   CHECK( sheet1Element.tagName(), QString("table") );
01563   CHECK( sheet1Element.hasAttributeNS(tableNS,"name"), true );
01564   CHECK( sheet1Element.attributeNS(tableNS,"name",""), QString("Sheet1") );
01565   CHECK( sheet1Element.attributeNS(tableNS,"style-name",""), QString("ta1") );
01566   CHECK( sheet1Element.attributeNS(tableNS,"print",""), QString("false") );
01567 
01568   //  KoXml::load( sheet1Element, 100 );
01569 
01570   // <table:table-column>
01571   KoXmlElement columnElement;
01572   columnElement = sheet1Element.firstChild().toElement();
01573   CHECK( columnElement.isNull(), false );
01574   CHECK( columnElement.isElement(), true );
01575   CHECK( columnElement.parentNode().isNull(), false );
01576   CHECK( columnElement.parentNode()==sheet1Element, true );
01577   CHECK( KoXml::childNodesCount(columnElement), 0 );
01578   CHECK( columnElement.firstChild().isNull(), true );
01579   CHECK( columnElement.lastChild().isNull(), true );
01580   CHECK( columnElement.previousSibling().isNull(), true );
01581   CHECK( columnElement.nextSibling().isNull(), false );
01582   CHECK( columnElement.tagName(), QString("table-column") );
01583   CHECK( columnElement.attributeNS(tableNS,"style-name",""), QString("co1") );
01584   CHECK( columnElement.attributeNS(tableNS,"default-cell-style-name",""), QString("Default") );
01585 
01586   // <table:table-row>
01587   KoXmlElement rowElement;
01588   rowElement = columnElement.nextSibling().toElement();
01589   CHECK( rowElement.isNull(), false );
01590   CHECK( rowElement.isElement(), true );
01591   CHECK( rowElement.parentNode().isNull(), false );
01592   CHECK( rowElement.parentNode()==sheet1Element, true );
01593   CHECK( KoXml::childNodesCount(rowElement), 1 );
01594   CHECK( rowElement.firstChild().isNull(), false );
01595   CHECK( rowElement.lastChild().isNull(), false );
01596   CHECK( rowElement.previousSibling().isNull(), false );
01597   CHECK( rowElement.nextSibling().isNull(), true );
01598   CHECK( rowElement.tagName(), QString("table-row") );
01599   CHECK( rowElement.attributeNS(tableNS,"style-name",""), QString("ro1") );
01600 
01601   // <table:table-cell>
01602   KoXmlElement cellElement;
01603   cellElement = rowElement.firstChild().toElement();
01604   CHECK( cellElement.isNull(), false );
01605   CHECK( cellElement.isElement(), true );
01606   CHECK( cellElement.parentNode().isNull(), false );
01607   CHECK( cellElement.parentNode()==rowElement, true );
01608   CHECK( KoXml::childNodesCount(cellElement), 1 );
01609   CHECK( cellElement.firstChild().isNull(), false );
01610   CHECK( cellElement.lastChild().isNull(), false );
01611   CHECK( cellElement.previousSibling().isNull(), true );
01612   CHECK( cellElement.nextSibling().isNull(), true );
01613   CHECK( cellElement.tagName(), QString("table-cell") );
01614   CHECK( cellElement.attributeNS(officeNS,"value-type",""), QString("string") );
01615   
01616   // <text:p>
01617   KoXmlElement parElement;
01618   parElement = cellElement.firstChild().toElement();
01619   CHECK( parElement.isNull(), false );
01620   CHECK( parElement.isElement(), true );
01621   CHECK( parElement.parentNode().isNull(), false );
01622   CHECK( parElement.parentNode()==cellElement, true );
01623   CHECK( KoXml::childNodesCount(parElement), 1 );
01624   CHECK( parElement.firstChild().isNull(), false );
01625   CHECK( parElement.lastChild().isNull(), false );
01626   CHECK( parElement.previousSibling().isNull(), true );
01627   CHECK( parElement.nextSibling().isNull(), true );
01628   CHECK( parElement.tagName(), QString("p") );
01629   CHECK( parElement.text(), QString("Hello, world") );
01630 
01631   // <table:table> for Sheet2
01632   KoXmlElement sheet2Element;
01633   sheet2Element = sheet1Element.nextSibling().toElement();
01634   CHECK( sheet2Element.isNull(), false );
01635   CHECK( sheet2Element.isElement(), true );
01636   CHECK( sheet2Element.parentNode().isNull(), false );
01637   CHECK( sheet2Element.parentNode()==spreadsheetElement, true );
01638   CHECK( KoXml::childNodesCount(sheet2Element), 2 );
01639   CHECK( sheet2Element.firstChild().isNull(), false );
01640   CHECK( sheet2Element.lastChild().isNull(), false );
01641   CHECK( sheet2Element.previousSibling().isNull(), false );
01642   CHECK( sheet2Element.nextSibling().isNull(), false );
01643   CHECK( sheet2Element.tagName(), QString("table") );
01644 
01645   // </table:table> for Sheet3
01646   KoXmlElement sheet3Element;
01647   sheet3Element = sheet2Element.nextSibling().toElement();
01648   CHECK( sheet3Element.isNull(), false );
01649   CHECK( sheet3Element.isElement(), true );
01650   CHECK( sheet3Element.parentNode().isNull(), false );
01651   CHECK( sheet3Element.parentNode()==spreadsheetElement, true );
01652   CHECK( KoXml::childNodesCount(sheet3Element), 2 );
01653   CHECK( sheet3Element.firstChild().isNull(), false );
01654   CHECK( sheet3Element.lastChild().isNull(), false );
01655   CHECK( sheet3Element.previousSibling().isNull(), false );
01656   CHECK( sheet3Element.nextSibling().isNull(), true );
01657   CHECK( sheet3Element.tagName(), QString("table") );
01658 }
01659 
01660 void testSimpleOpenDocumentPresentation()
01661 {
01662   QString errorMsg;
01663   int errorLine = 0;
01664   int errorColumn = 0;
01665 
01666   QBuffer xmldevice;
01667   xmldevice.open( QIODevice::WriteOnly );
01668   QTextStream xmlstream( &xmldevice );
01669   
01670   // content.xml from a simple OpenDocument presentation
01671   // styles, declarations and unnecessary namespaces are omitted
01672   // the first page is "Title" and has two text boxes
01673   // the second page is 
01674 
01675   xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
01676   xmlstream << "<office:document-content ";
01677   xmlstream << "  xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
01678   xmlstream << "  xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
01679   xmlstream << "  xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" ";
01680   xmlstream << "  xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" ";
01681   xmlstream << "  xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" ";
01682   xmlstream << "  office:version=\"1.0\">";
01683   xmlstream << " <office:scripts/>";
01684   xmlstream << " <office:automatic-styles/>";
01685   xmlstream << " <office:body>";
01686   xmlstream << "  <office:presentation>";
01687   xmlstream << "   <draw:page draw:name=\"Title\" draw:style-name=\"dp1\" ";
01688   xmlstream << "      draw:master-page-name=\"lyt-cool\" ";
01689   xmlstream << "      presentation:presentation-page-layout-name=\"AL1T0\">";
01690   xmlstream << "    <draw:frame presentation:style-name=\"pr1\" ";
01691   xmlstream << "      draw:text-style-name=\"P2\" draw:layer=\"layout\" ";
01692   xmlstream << "      svg:width=\"23.912cm\" svg:height=\"3.508cm\" ";
01693   xmlstream << "      svg:x=\"2.058cm\" svg:y=\"1.543cm\" ";
01694   xmlstream << "      presentation:class=\"title\" ";
01695   xmlstream << "      presentation:user-transformed=\"true\">";
01696   xmlstream << "     <draw:text-box>";
01697   xmlstream << "      <text:p text:style-name=\"P1\">Foobar</text:p>";
01698   xmlstream << "     </draw:text-box>";
01699   xmlstream << "    </draw:frame>";
01700   xmlstream << "    <draw:frame presentation:style-name=\"pr2\" ";
01701   xmlstream << "      draw:text-style-name=\"P3\" draw:layer=\"layout\"";
01702   xmlstream << "      svg:width=\"23.912cm\" svg:height=\"13.231cm\"";
01703   xmlstream << "      svg:x=\"2.058cm\" svg:y=\"5.838cm\" ";
01704   xmlstream << "      presentation:class=\"subtitle\">";
01705   xmlstream << "     <draw:text-box>";
01706   xmlstream << "      <text:p text:style-name=\"P3\">Foo</text:p>";
01707   xmlstream << "     </draw:text-box>";
01708   xmlstream << "    </draw:frame>";
01709   xmlstream << "    <presentation:notes draw:style-name=\"dp2\">";
01710   xmlstream << "     <draw:page-thumbnail draw:style-name=\"gr1\" draw:layer=\"layout\" svg:width=\"13.706cm\" svg:height=\"10.28cm\" svg:x=\"3.647cm\" svg:y=\"2.853cm\" draw:page-number=\"1\" presentation:class=\"page\"/>";
01711   xmlstream << "     <draw:frame presentation:style-name=\"pr3\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\"14.518cm\" svg:height=\"11.411cm\" svg:x=\"3.249cm\" svg:y=\"14.13cm\" presentation:class=\"notes\" presentation:placeholder=\"true\">";
01712   xmlstream << "      <draw:text-box/>";
01713   xmlstream << "     </draw:frame>";
01714   xmlstream << "    </presentation:notes>";
01715   xmlstream << "   </draw:page>";
01716   xmlstream << "   <presentation:settings presentation:stay-on-top=\"true\"/>";
01717   xmlstream << "  </office:presentation>";
01718   xmlstream << " </office:body>";
01719   xmlstream << "</office:document-content>";
01720   xmldevice.close();
01721 
01722   KoXmlDocument doc;
01723   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
01724   CHECK( errorMsg.isEmpty(), true );
01725   CHECK( errorLine, 0 );
01726   CHECK( errorColumn, 0 );
01727 
01728   const char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; 
01729   const char* drawNS = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";
01730   const char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
01731   const char* presentationNS = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";
01732   const char* svgNS = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
01733 
01734   // <office:document-content>
01735   KoXmlElement contentElement;
01736   contentElement = doc.documentElement();
01737   CHECK( contentElement.isNull(), false );
01738   
01739   CHECK( contentElement.isElement(), true );
01740   CHECK( contentElement.parentNode().isNull(), false );
01741   CHECK( contentElement.parentNode().toDocument()==doc, true );
01742   CHECK( KoXml::childNodesCount(contentElement), 3 );
01743   CHECK( contentElement.firstChild().isNull(), false );
01744   CHECK( contentElement.lastChild().isNull(), false );
01745   CHECK( contentElement.previousSibling().isNull(), false );
01746   CHECK( contentElement.nextSibling().isNull(), true );
01747   CHECK( contentElement.localName(), QString("document-content") );
01748   CHECK( contentElement.hasAttributeNS(officeNS,"version"), true );
01749   CHECK( contentElement.attributeNS(officeNS,"version",""), QString("1.0") );
01750 
01751   // <office:scripts>
01752   KoXmlElement scriptsElement;
01753   scriptsElement = KoXml::namedItemNS( contentElement, officeNS, "scripts" );
01754   CHECK( scriptsElement.isNull(), false );
01755   CHECK( scriptsElement.isElement(), true );
01756   CHECK( scriptsElement.parentNode().isNull(), false );
01757   CHECK( scriptsElement.parentNode()==contentElement, true );
01758   CHECK( KoXml::childNodesCount(scriptsElement), 0 );
01759   CHECK( scriptsElement.firstChild().isNull(), true );
01760   CHECK( scriptsElement.lastChild().isNull(), true );
01761   CHECK( scriptsElement.previousSibling().isNull(), true );
01762   CHECK( scriptsElement.nextSibling().isNull(), false );
01763   CHECK( scriptsElement.localName(), QString("scripts") );
01764   
01765   // <office:automatic-styles>
01766   KoXmlElement stylesElement;
01767   stylesElement = KoXml::namedItemNS( contentElement, officeNS, "automatic-styles" );
01768   CHECK( stylesElement.isNull(), false );
01769   CHECK( stylesElement.isElement(), true );
01770   CHECK( stylesElement.parentNode().isNull(), false );
01771   CHECK( stylesElement.parentNode()==contentElement, true );
01772   CHECK( KoXml::childNodesCount(stylesElement), 0 );
01773   CHECK( stylesElement.firstChild().isNull(), true );
01774   CHECK( stylesElement.lastChild().isNull(), true );
01775   CHECK( stylesElement.previousSibling().isNull(), false );
01776   CHECK( stylesElement.nextSibling().isNull(), false );
01777   CHECK( stylesElement.localName(), QString("automatic-styles") );
01778   
01779   // also same <office:automatic-styles>, but without namedItemNS
01780   KoXmlNode styles2Element;
01781   styles2Element = scriptsElement.nextSibling().toElement();
01782   CHECK( styles2Element.isNull(), false );
01783   CHECK( styles2Element.isElement(), true );
01784   CHECK( styles2Element.parentNode().isNull(), false );
01785   CHECK( styles2Element.parentNode()==contentElement, true );
01786   CHECK( KoXml::childNodesCount(styles2Element), 0 );
01787   CHECK( styles2Element.firstChild().isNull(), true );
01788   CHECK( styles2Element.lastChild().isNull(), true );
01789   CHECK( styles2Element.previousSibling().isNull(), false );
01790   CHECK( styles2Element.nextSibling().isNull(), false );
01791   CHECK( styles2Element.localName(), QString("automatic-styles") );
01792 
01793   // <office:body>
01794   KoXmlElement bodyElement;
01795   bodyElement = KoXml::namedItemNS( contentElement, officeNS, "body" );
01796   CHECK( bodyElement.isNull(), false );
01797   CHECK( bodyElement.isElement(), true );
01798   CHECK( bodyElement.parentNode().isNull(), false );
01799   CHECK( bodyElement.parentNode()==contentElement, true );
01800   CHECK( KoXml::childNodesCount(bodyElement), 1 );
01801   CHECK( bodyElement.firstChild().isNull(), false );
01802   CHECK( bodyElement.lastChild().isNull(), false );
01803   CHECK( bodyElement.previousSibling().isNull(), false );
01804   CHECK( bodyElement.nextSibling().isNull(), true );
01805   CHECK( bodyElement.localName(), QString("body") );
01806 
01807   // also same <office:body>, but without namedItemNS
01808   KoXmlElement body2Element;
01809   body2Element = stylesElement.nextSibling().toElement();
01810   CHECK( body2Element.isNull(), false );
01811   CHECK( body2Element.isElement(), true );
01812   CHECK( body2Element.parentNode().isNull(), false );
01813   CHECK( body2Element.parentNode()==contentElement, true );
01814   CHECK( KoXml::childNodesCount(body2Element), 1 );
01815   CHECK( body2Element.firstChild().isNull(), false );
01816   CHECK( body2Element.lastChild().isNull(), false );
01817   CHECK( body2Element.previousSibling().isNull(), false );
01818   CHECK( body2Element.nextSibling().isNull(), true );
01819   CHECK( body2Element.localName(), QString("body") );
01820 
01821   // <office:presentation>
01822   KoXmlElement presentationElement;
01823   presentationElement = KoXml::namedItemNS( bodyElement, officeNS, "presentation" );
01824   CHECK( presentationElement.isNull(), false );
01825   CHECK( presentationElement.isElement(), true );
01826   CHECK( presentationElement.parentNode().isNull(), false );
01827   CHECK( presentationElement.parentNode()==bodyElement, true );
01828   CHECK( KoXml::childNodesCount(presentationElement), 2 );
01829   CHECK( presentationElement.firstChild().isNull(), false );
01830   CHECK( presentationElement.lastChild().isNull(), false );
01831   CHECK( presentationElement.previousSibling().isNull(), true );
01832   CHECK( presentationElement.nextSibling().isNull(), true );
01833   CHECK( presentationElement.localName(), QString("presentation") );
01834 
01835   // the same <office:presentation>, but without namedItemNS
01836   KoXmlElement presentation2Element;
01837   presentation2Element = bodyElement.firstChild().toElement();
01838   CHECK( presentation2Element.isNull(), false );
01839   CHECK( presentation2Element.isElement(), true );
01840   CHECK( presentation2Element.parentNode().isNull(), false );
01841   CHECK( presentation2Element.parentNode()==bodyElement, true );
01842   CHECK( KoXml::childNodesCount(presentation2Element), 2 );
01843   CHECK( presentation2Element.firstChild().isNull(), false );
01844   CHECK( presentation2Element.lastChild().isNull(), false );
01845   CHECK( presentation2Element.previousSibling().isNull(), true );
01846   CHECK( presentation2Element.nextSibling().isNull(), true );
01847   CHECK( presentation2Element.localName(), QString("presentation") );
01848 
01849   // <draw:page> for "Title"
01850   KoXmlElement titlePageElement;
01851   titlePageElement = presentationElement.firstChild().toElement();
01852   CHECK( titlePageElement.isNull(), false );
01853   CHECK( titlePageElement.isElement(), true );
01854   CHECK( titlePageElement.parentNode().isNull(), false );
01855   CHECK( titlePageElement.parentNode()==presentationElement, true );
01856   CHECK( KoXml::childNodesCount(titlePageElement), 3 );
01857   CHECK( titlePageElement.firstChild().isNull(), false );
01858   CHECK( titlePageElement.lastChild().isNull(), false );
01859   CHECK( titlePageElement.previousSibling().isNull(), true );
01860   CHECK( titlePageElement.nextSibling().isNull(), false );
01861   CHECK( titlePageElement.localName(), QString("page") );
01862   CHECK( titlePageElement.attributeNS(drawNS,"name",""), QString("Title") );
01863   CHECK( titlePageElement.attributeNS(drawNS,"style-name",""), QString("dp1") );
01864   CHECK( titlePageElement.attributeNS(drawNS,"master-page-name",""), QString("lyt-cool") );
01865   CHECK( titlePageElement.attributeNS(presentationNS,
01866     "presentation-page-layout-name",""), QString("AL1T0") );
01867 
01868   // <draw:frame> for the title frame
01869   KoXmlElement titleFrameElement;
01870   titleFrameElement = titlePageElement.firstChild().toElement();
01871   CHECK( titleFrameElement.isNull(), false );
01872   CHECK( titleFrameElement.isElement(), true );
01873   CHECK( titleFrameElement.parentNode().isNull(), false );
01874   CHECK( titleFrameElement.parentNode()==titlePageElement, true );
01875   CHECK( KoXml::childNodesCount(titleFrameElement), 1 );
01876   CHECK( titleFrameElement.firstChild().isNull(), false );
01877   CHECK( titleFrameElement.lastChild().isNull(), false );
01878   CHECK( titleFrameElement.previousSibling().isNull(), true );
01879   CHECK( titleFrameElement.nextSibling().isNull(), false );
01880   CHECK( titleFrameElement.localName(), QString("frame") );
01881   CHECK( titleFrameElement.attributeNS(presentationNS,"style-name",""), QString("pr1") );
01882   CHECK( titleFrameElement.attributeNS(presentationNS,"class",""), QString("title") );
01883   CHECK( titleFrameElement.attributeNS(presentationNS,"user-transformed",""), QString("true") );
01884   CHECK( titleFrameElement.attributeNS(drawNS,"text-style-name",""), QString("P2") );
01885   CHECK( titleFrameElement.attributeNS(drawNS,"layer",""), QString("layout") );
01886   CHECK( titleFrameElement.attributeNS(svgNS,"width",""), QString("23.912cm") );
01887   CHECK( titleFrameElement.attributeNS(svgNS,"height",""), QString("3.508cm") );
01888   CHECK( titleFrameElement.attributeNS(svgNS,"x",""), QString("2.058cm") );
01889   CHECK( titleFrameElement.attributeNS(svgNS,"y",""), QString("1.543cm") );
01890   
01891   // <draw:text-box> of the title frame
01892   KoXmlElement titleBoxElement;
01893   titleBoxElement = titleFrameElement.firstChild().toElement();
01894   CHECK( titleBoxElement.isNull(), false );
01895   CHECK( titleBoxElement.isElement(), true );
01896   CHECK( titleBoxElement.parentNode().isNull(), false );
01897   CHECK( titleBoxElement.parentNode()==titleFrameElement, true );
01898   CHECK( KoXml::childNodesCount(titleBoxElement), 1 );
01899   CHECK( titleBoxElement.firstChild().isNull(), false );
01900   CHECK( titleBoxElement.lastChild().isNull(), false );
01901   CHECK( titleBoxElement.previousSibling().isNull(), true );
01902   CHECK( titleBoxElement.nextSibling().isNull(), true );
01903   CHECK( titleBoxElement.localName(), QString("text-box") );
01904   
01905   // <text:p> for the title text-box
01906   KoXmlElement titleParElement;
01907   titleParElement = titleBoxElement.firstChild().toElement();
01908   CHECK( titleParElement.isNull(), false );
01909   CHECK( titleParElement.isElement(), true );
01910   CHECK( titleParElement.parentNode().isNull(), false );
01911   CHECK( titleParElement.parentNode()==titleBoxElement, true );
01912   CHECK( KoXml::childNodesCount(titleParElement), 1 );
01913   CHECK( titleParElement.firstChild().isNull(), false );
01914   CHECK( titleParElement.lastChild().isNull(), false );
01915   CHECK( titleParElement.previousSibling().isNull(), true );
01916   CHECK( titleParElement.nextSibling().isNull(), true );
01917   CHECK( titleParElement.localName(), QString("p") );
01918   CHECK( titleParElement.attributeNS(textNS,"style-name",""), QString("P1") );
01919   CHECK( titleParElement.text(), QString("Foobar") );
01920 
01921   // <draw:frame> for the subtitle frame
01922   KoXmlElement subtitleFrameElement;
01923   subtitleFrameElement = titleFrameElement.nextSibling().toElement();
01924   CHECK( subtitleFrameElement.isNull(), false );
01925   CHECK( subtitleFrameElement.isElement(), true );
01926   CHECK( subtitleFrameElement.parentNode().isNull(), false );
01927   CHECK( subtitleFrameElement.parentNode()==titlePageElement, true );
01928   CHECK( KoXml::childNodesCount(subtitleFrameElement), 1 );
01929   CHECK( subtitleFrameElement.firstChild().isNull(), false );
01930   CHECK( subtitleFrameElement.lastChild().isNull(), false );
01931   CHECK( subtitleFrameElement.previousSibling().isNull(), false );
01932   CHECK( subtitleFrameElement.nextSibling().isNull(), false );
01933   CHECK( subtitleFrameElement.localName(), QString("frame") );
01934   CHECK( subtitleFrameElement.attributeNS(presentationNS,"style-name",""), QString("pr2") );
01935   CHECK( subtitleFrameElement.attributeNS(presentationNS,"class",""), QString("subtitle") );
01936   CHECK( subtitleFrameElement.hasAttributeNS(presentationNS,"user-transformed"), false );
01937   CHECK( subtitleFrameElement.attributeNS(drawNS,"text-style-name",""), QString("P3") );
01938   CHECK( subtitleFrameElement.attributeNS(drawNS,"layer",""), QString("layout") );
01939   CHECK( subtitleFrameElement.attributeNS(svgNS,"width",""), QString("23.912cm") );
01940   CHECK( subtitleFrameElement.attributeNS(svgNS,"height",""), QString("13.231cm") );
01941   CHECK( subtitleFrameElement.attributeNS(svgNS,"x",""), QString("2.058cm") );
01942   CHECK( subtitleFrameElement.attributeNS(svgNS,"y",""), QString("5.838cm") );
01943 
01944   // <draw:text-box> of the subtitle frame
01945   KoXmlElement subtitleBoxElement;
01946   subtitleBoxElement = subtitleFrameElement.firstChild().toElement();
01947   CHECK( subtitleBoxElement.isNull(), false );
01948   CHECK( subtitleBoxElement.isElement(), true );
01949   CHECK( subtitleBoxElement.parentNode().isNull(), false );
01950   CHECK( subtitleBoxElement.parentNode()==subtitleFrameElement, true );
01951   CHECK( KoXml::childNodesCount(subtitleBoxElement), 1 );
01952   CHECK( subtitleBoxElement.firstChild().isNull(), false );
01953   CHECK( subtitleBoxElement.lastChild().isNull(), false );
01954   CHECK( subtitleBoxElement.previousSibling().isNull(), true );
01955   CHECK( subtitleBoxElement.nextSibling().isNull(), true );
01956   CHECK( subtitleBoxElement.localName(), QString("text-box") );
01957  
01958   // <text:p> for the subtitle text-box
01959   KoXmlElement subtitleParElement;
01960   subtitleParElement = subtitleBoxElement.firstChild().toElement();
01961   CHECK( subtitleParElement.isNull(), false );
01962   CHECK( subtitleParElement.isElement(), true );
01963   CHECK( subtitleParElement.parentNode().isNull(), false );
01964   CHECK( subtitleParElement.parentNode()==subtitleBoxElement, true );
01965   CHECK( KoXml::childNodesCount(subtitleParElement), 1 );
01966   CHECK( subtitleParElement.firstChild().isNull(), false );
01967   CHECK( subtitleParElement.lastChild().isNull(), false );
01968   CHECK( subtitleParElement.previousSibling().isNull(), true );
01969   CHECK( subtitleParElement.nextSibling().isNull(), true );
01970   CHECK( subtitleParElement.localName(), QString("p") );
01971   CHECK( subtitleParElement.attributeNS(textNS,"style-name",""), QString("P3") );
01972   CHECK( subtitleParElement.text(), QString("Foo") );
01973 }
01974 
01975 void testSimpleOpenDocumentFormula()
01976 {
01977   QString errorMsg;
01978   int errorLine = 0;
01979   int errorColumn = 0;
01980 
01981   QBuffer xmldevice;
01982   xmldevice.open( QIODevice::WriteOnly );
01983   QTextStream xmlstream( &xmldevice );
01984   
01985   // content.xml from a simple OpenDocument formula
01986   // this is essentially MathML
01987   xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
01988   xmlstream << "<!DOCTYPE math:math PUBLIC \"-//OpenOffice.org//DTD Modified W3C MathML 1.01//EN\" \"math.dtd\">";
01989   xmlstream << "<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">";
01990   xmlstream << " <math:semantics>";
01991   xmlstream << "  <math:mrow>";
01992   xmlstream << "   <math:mi>E</math:mi>";
01993   xmlstream << "   <math:mo math:stretchy=\"false\">=</math:mo>";
01994   xmlstream << "   <math:msup>";
01995   xmlstream << "    <math:mi math:fontstyle=\"italic\">mc</math:mi>";
01996   xmlstream << "    <math:mn>2</math:mn>";
01997   xmlstream << "   </math:msup>";
01998   xmlstream << "  </math:mrow>";
01999   xmlstream << "  <math:annotation math:encoding=\"StarMath 5.0\">E  =  mc^2 </math:annotation>";
02000   xmlstream << " </math:semantics>";
02001   xmlstream << "</math:math>";
02002   xmldevice.close();
02003 
02004   KoXmlDocument doc;
02005   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
02006   CHECK( errorMsg.isEmpty(), true );
02007   CHECK( errorLine, 0 );
02008   CHECK( errorColumn, 0 );
02009 
02010   const char* mathNS = "http://www.w3.org/1998/Math/MathML";
02011 
02012   // <math:math>
02013   KoXmlElement mathElement;
02014   mathElement = doc.documentElement();
02015   CHECK( mathElement.isNull(), false );
02016   CHECK( mathElement.isElement(), true );
02017   CHECK( mathElement.parentNode().isNull(), false );
02018   CHECK( mathElement.parentNode().toDocument()==doc, true );
02019   CHECK( mathElement.firstChild().isNull(), false );
02020   CHECK( mathElement.lastChild().isNull(), false );
02021   CHECK( mathElement.previousSibling().isNull(), false );
02022   CHECK( mathElement.nextSibling().isNull(), true );
02023   CHECK( mathElement.localName(), QString("math") );
02024   
02025   // <math:semantics>
02026   KoXmlElement semanticsElement;
02027   semanticsElement = KoXml::namedItemNS( mathElement, mathNS, "semantics" );
02028   CHECK( semanticsElement.isNull(), false );
02029   CHECK( semanticsElement.isElement(), true );
02030   CHECK( semanticsElement.parentNode().isNull(), false );
02031   CHECK( semanticsElement.parentNode().toElement()==mathElement, true );
02032   CHECK( semanticsElement.firstChild().isNull(), false );
02033   CHECK( semanticsElement.lastChild().isNull(), false );
02034   CHECK( semanticsElement.previousSibling().isNull(), true );
02035   CHECK( semanticsElement.nextSibling().isNull(), true );
02036   CHECK( semanticsElement.localName(), QString("semantics") );
02037     
02038   // the same <math:semantics> but without namedItemNS
02039   KoXmlElement semantics2Element;
02040   semantics2Element = mathElement.firstChild().toElement();
02041   CHECK( semantics2Element.isNull(), false );
02042   CHECK( semantics2Element.isElement(), true );
02043   CHECK( semantics2Element.parentNode().isNull(), false );
02044   CHECK( semantics2Element.parentNode().toElement()==mathElement, true );
02045   CHECK( semantics2Element.firstChild().isNull(), false );
02046   CHECK( semantics2Element.lastChild().isNull(), false );
02047   CHECK( semantics2Element.previousSibling().isNull(), true );
02048   CHECK( semantics2Element.nextSibling().isNull(), true );
02049   CHECK( semantics2Element.localName(), QString("semantics") );
02050 
02051   // <math:mrow>
02052   KoXmlElement mrowElement;
02053   mrowElement = semanticsElement.firstChild().toElement();
02054   CHECK( mrowElement.isNull(), false );
02055   CHECK( mrowElement.isElement(), true );
02056   CHECK( mrowElement.parentNode().isNull(), false );
02057   CHECK( mrowElement.parentNode().toElement()==semanticsElement, true );
02058   CHECK( mrowElement.firstChild().isNull(), false );
02059   CHECK( mrowElement.lastChild().isNull(), false );
02060   CHECK( mrowElement.previousSibling().isNull(), true );
02061   CHECK( mrowElement.nextSibling().isNull(), false );
02062   CHECK( mrowElement.localName(), QString("mrow") );
02063 
02064   // <math:mi> for "E"
02065   KoXmlElement miElement;
02066   miElement = mrowElement.firstChild().toElement();
02067   CHECK( miElement.isNull(), false );
02068   CHECK( miElement.isElement(), true );
02069   CHECK( miElement.parentNode().isNull(), false );
02070   CHECK( miElement.parentNode().toElement()==mrowElement, true );
02071   CHECK( miElement.firstChild().isNull(), false );
02072   CHECK( miElement.lastChild().isNull(), false );
02073   CHECK( miElement.previousSibling().isNull(), true );
02074   CHECK( miElement.nextSibling().isNull(), false );
02075   CHECK( miElement.localName(), QString("mi") );
02076 
02077   // <math:mo> for "="
02078   KoXmlElement moElement;
02079   moElement = miElement.nextSibling().toElement();
02080   CHECK( moElement.isNull(), false );
02081   CHECK( moElement.isElement(), true );
02082   CHECK( moElement.parentNode().isNull(), false );
02083   CHECK( moElement.parentNode().toElement()==mrowElement, true );
02084   CHECK( moElement.firstChild().isNull(), false );
02085   CHECK( moElement.lastChild().isNull(), false );
02086   CHECK( moElement.previousSibling().isNull(), false );
02087   CHECK( moElement.nextSibling().isNull(), false );
02088   CHECK( moElement.localName(), QString("mo") );
02089   CHECK( moElement.attributeNS(mathNS,"stretchy",""), QString("false") );
02090 
02091   // <math:msup> for "mc" and superscripted "2"
02092   KoXmlElement msupElement;
02093   msupElement = moElement.nextSibling().toElement();
02094   CHECK( msupElement.isNull(), false );
02095   CHECK( msupElement.isElement(), true );
02096   CHECK( msupElement.parentNode().isNull(), false );
02097   CHECK( msupElement.parentNode().toElement()==mrowElement, true );
02098   CHECK( msupElement.firstChild().isNull(), false );
02099   CHECK( msupElement.lastChild().isNull(), false );
02100   CHECK( msupElement.previousSibling().isNull(), false );
02101   CHECK( msupElement.nextSibling().isNull(), true );
02102   CHECK( msupElement.localName(), QString("msup") );
02103   
02104   // <math:mi> inside the <math:msup> for "mc"
02105   KoXmlElement mcElement;
02106   mcElement = msupElement.firstChild().toElement();
02107   CHECK( mcElement.isNull(), false );
02108   CHECK( mcElement.isElement(), true );
02109   CHECK( mcElement.parentNode().isNull(), false );
02110   CHECK( mcElement.parentNode().toElement()==msupElement, true );
02111   CHECK( mcElement.firstChild().isNull(), false );
02112   CHECK( mcElement.lastChild().isNull(), false );
02113   CHECK( mcElement.previousSibling().isNull(), true );
02114   CHECK( mcElement.nextSibling().isNull(), false );
02115   CHECK( mcElement.localName(), QString("mi") );
02116   CHECK( mcElement.text(), QString("mc") );
02117   CHECK( mcElement.attributeNS(mathNS,"fontstyle",""), QString("italic") );
02118   
02119   // <math:mn> inside the <math:msup> for "2" (superscript)
02120   KoXmlElement mnElement;
02121   mnElement = mcElement.nextSibling().toElement();
02122   CHECK( mnElement.isNull(), false );
02123   CHECK( mnElement.isElement(), true );
02124   CHECK( mnElement.parentNode().isNull(), false );
02125   CHECK( mnElement.parentNode().toElement()==msupElement, true );
02126   CHECK( mnElement.firstChild().isNull(), false );
02127   CHECK( mnElement.lastChild().isNull(), false );
02128   CHECK( mnElement.previousSibling().isNull(), false );
02129   CHECK( mnElement.nextSibling().isNull(), true );
02130   CHECK( mnElement.localName(), QString("mn") );
02131   CHECK( mnElement.text(), QString("2") );
02132   
02133   // <math:annotation>
02134   KoXmlElement annotationElement;
02135   annotationElement = semanticsElement.lastChild().toElement();
02136   CHECK( annotationElement.isNull(), false );
02137   CHECK( annotationElement.isElement(), true );
02138   CHECK( annotationElement.parentNode().isNull(), false );
02139   CHECK( annotationElement.parentNode().toElement()==semanticsElement, true );
02140   CHECK( annotationElement.firstChild().isNull(), false );
02141   CHECK( annotationElement.lastChild().isNull(), false );
02142   CHECK( annotationElement.previousSibling().isNull(), false );
02143   CHECK( annotationElement.nextSibling().isNull(), true );
02144   CHECK( annotationElement.localName(), QString("annotation") );
02145   CHECK( annotationElement.text(), QString("E  =  mc^2 ") );
02146   CHECK( annotationElement.attributeNS(mathNS,"encoding",""), QString("StarMath 5.0") );
02147 }
02148 
02149 void testLargeOpenDocumentSpreadsheet()
02150 {
02151   QString errorMsg;
02152   int errorLine = 0;
02153   int errorColumn = 0;
02154 
02155   int sheetCount = 4;
02156   int rowCount = 200;
02157   int colCount = 200/16;
02158 
02159   QBuffer xmldevice;
02160   xmldevice.open( QIODevice::WriteOnly );
02161   QTextStream xmlstream( &xmldevice );
02162   
02163   // content.xml
02164   xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
02165   xmlstream << "<office:document-content ";
02166   xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
02167   xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
02168   xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" >\n";
02169   xmlstream << "<office:body>\n";
02170   xmlstream << "<office:spreadsheet>\n";
02171   for( int i = 0; i < sheetCount; i++ )
02172   {
02173     QString sheetName = QString("Sheet%1").arg(i+1);
02174     xmlstream << "<table:table table:name=\"" << sheetName;
02175     xmlstream << "\" table:print=\"false\">\n";
02176     for( int j = 0; j < rowCount; j++ )
02177     {
02178       xmlstream << "<table:table-row>\n";
02179       for( int k = 0; k < colCount; k++ )
02180       {
02181         xmlstream << "<table:table-cell office:value-type=\"string\">";
02182         xmlstream << "<text:p>Hello, world</text:p>";
02183         xmlstream << "</table:table-cell>\n";
02184       }
02185       xmlstream << "</table:table-row>\n";
02186     }
02187     xmlstream << "</table:table>\n";
02188   }
02189   xmlstream << "</office:spreadsheet>\n";
02190   xmlstream << "</office:body>\n";
02191   xmlstream << "</office:document-content>\n";
02192   xmldevice.close();
02193 
02194   printf("Raw XML size: %lld KB\n", xmldevice.size()/1024 );
02195 
02196 
02197   QTime timer;
02198 
02199 #if 0
02200   // just to test parsing speed with plain dumb handler
02201   QXmlSimpleReader* reader = new QXmlSimpleReader;
02202   reader->setFeature( "http://xml.org/sax/features/namespaces", true );
02203   QXmlDefaultHandler handler;
02204   reader->setContentHandler( &handler );
02205   reader->setErrorHandler( &handler );
02206   reader->setLexicalHandler( &handler );
02207   reader->setDeclHandler( &handler );
02208   reader->setDTDHandler( &handler );
02209   QXmlInputSource xmlSource( &xmldevice );
02210   timer.start();
02211   reader->parse( &xmlSource ); 
02212   printf("Large spreadsheet: QXmlDefaultHandler parsing time is %d ms\n", timer.elapsed() );
02213   delete reader;
02214   xmldevice.seek( 0 );
02215 #endif
02216 
02217   KoXmlDocument doc;
02218 
02219   timer.start();
02220   CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
02221   CHECK( errorMsg.isEmpty(), true );
02222   CHECK( errorLine, 0 );
02223   CHECK( errorColumn, 0 );
02224   
02225   if( !errorMsg.isEmpty() )
02226   {
02227     qDebug("Error: %s", qPrintable( errorMsg ) );
02228     return;
02229   }
02230 
02231   printf("Large spreadsheet: KoXmlDocument parsing time is %d ms\n", timer.elapsed() );
02232   
02233   // release memory taken by the XML document content
02234   //xmlstream.setDevice( 0 );
02235 
02236   // namespaces that will be used  
02237   QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; 
02238   QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
02239   QString textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
02240 
02241   // <office:document-content>
02242   KoXmlElement contentElement;
02243   contentElement = doc.documentElement();
02244   CHECK( contentElement.isNull(), false );
02245   CHECK( contentElement.isElement(), true );
02246   CHECK( contentElement.localName(), QString("document-content") );
02247   
02248   // <office:body>
02249   KoXmlElement bodyElement;
02250   bodyElement = contentElement.firstChild().toElement();
02251   CHECK( bodyElement.isNull(), false );
02252   CHECK( bodyElement.isElement(), true );
02253   CHECK( bodyElement.localName(), QString("body") );
02254 
02255   // <office:spreadsheet>
02256   KoXmlElement spreadsheetElement;
02257   spreadsheetElement = bodyElement.firstChild().toElement();
02258   CHECK( spreadsheetElement.isNull(), false );
02259   CHECK( spreadsheetElement.isElement(), true );
02260   CHECK( spreadsheetElement.localName(), QString("spreadsheet") );
02261 
02262   // now we visit every sheet, every row, every cell
02263   timer.start();
02264   KoXmlElement tableElement;
02265   tableElement = spreadsheetElement.firstChild().toElement();
02266   for( int table=0; table < sheetCount; table++ )
02267   {
02268     QString tableName = QString("Sheet%1").arg(table+1);
02269     CHECK( tableElement.isNull(), false );
02270     CHECK( tableElement.isElement(), true );
02271     CHECK( tableElement.localName(), QString("table") );
02272     CHECK( tableElement.hasAttributeNS(tableNS,"name"), true );
02273     CHECK( tableElement.attributeNS(tableNS,"name",""), tableName );
02274     CHECK( tableElement.attributeNS(tableNS,"print",""), QString("false") );
02275 
02276     // load everything for this table
02277     //KoXml::load( tableElement, 99 );
02278 
02279     CHECK( tableElement.parentNode().isNull(), false );
02280     CHECK( tableElement.parentNode()==spreadsheetElement, true );
02281     CHECK( tableElement.firstChild().isNull(), false );
02282     CHECK( tableElement.lastChild().isNull(), false );
02283 
02284     KoXmlElement rowElement;
02285     rowElement = tableElement.firstChild().toElement();
02286     for( int row=0; row < rowCount; row++ )
02287     {
02288       CHECK( rowElement.isNull(), false );
02289       CHECK( rowElement.isElement(), true );
02290       CHECK( rowElement.localName(), QString("table-row") );
02291       CHECK( rowElement.parentNode().isNull(), false );
02292       CHECK( rowElement.parentNode()==tableElement, true );
02293       CHECK( rowElement.firstChild().isNull(), false );
02294       CHECK( rowElement.lastChild().isNull(), false );
02295 
02296       KoXmlElement cellElement;
02297       cellElement = rowElement.firstChild().toElement();
02298       for( int col=0; col < colCount; col++ )
02299       {
02300         CHECK( cellElement.isNull(), false );
02301         CHECK( cellElement.isElement(), true );
02302         CHECK( cellElement.localName(), QString("table-cell") );
02303         CHECK( cellElement.text(), QString("Hello, world") );
02304         CHECK( cellElement.hasAttributeNS(officeNS,"value-type"), true );
02305         CHECK( cellElement.attributeNS(officeNS,"value-type",""), QString("string" ) );
02306         CHECK( cellElement.parentNode().isNull(), false );
02307         CHECK( cellElement.parentNode()==rowElement, true );
02308         CHECK( cellElement.firstChild().isNull(), false );
02309         CHECK( cellElement.lastChild().isNull(), false );
02310         cellElement = cellElement.nextSibling().toElement();
02311       }
02312 
02313       //KoXml::unload( rowElement );
02314       rowElement = rowElement.nextSibling().toElement();
02315     }
02316 
02317     KoXml::unload( tableElement );
02318     tableElement = tableElement.nextSibling().toElement();
02319   }
02320 
02321   printf("Large spreadsheet: iterating time is %d ms\n", timer.elapsed() );
02322 }
02323 
02324 
02325 void testExternalOpenDocumentSpreadsheet(const QString& filename)
02326 {
02327   QProcess unzip;
02328   QStringList arguments;
02329   arguments << "-o" << filename << "content.xml";
02330   
02331   printf( "Unzipping content.xml from %s...\n", qPrintable( filename ) );
02332   
02333   unzip.start( "unzip", arguments );
02334   if( !unzip.waitForStarted() )
02335   {
02336     printf( "Error: can't invoke unzip. Check your PATH and installation!\n\n" );
02337     return;
02338   }
02339   
02340   if( !unzip.waitForFinished() )
02341   {
02342     printf( "Error: unzip failed, can't continue!\n\n" );
02343     return;
02344   }
02345   
02346   printf( "Procesing content.xml....\n" );
02347   
02348   QString errorMsg;
02349   int errorLine = 0;
02350   int errorColumn = 0;
02351   
02352   QFile xmlfile( "content.xml" );
02353   if( !xmlfile.open(QFile::ReadOnly) )
02354   {
02355     printf("Can not open file '%s'\n", qPrintable(filename));
02356     return;
02357   }
02358   
02359   printf("Test external file: %s   %lld KB\n", qPrintable(filename), xmlfile.size()/1024);
02360   
02361   QTime timer;
02362   timer.start();
02363 
02364   KoXmlDocument doc;
02365   
02366   CHECK( KoXml::setDocument( doc, &xmlfile, true, &errorMsg, &errorLine, &errorColumn ), true );
02367   CHECK( errorMsg.isEmpty(), true );
02368   CHECK( errorLine, 0 );
02369   CHECK( errorColumn, 0 );
02370 
02371   printf("External spreadsheet: parsing time is %d ms\n", timer.elapsed() );
02372 
02373   // namespaces that will be used  
02374   QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; 
02375   QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
02376   QString textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
02377 
02378   // <office:document-content>
02379   KoXmlElement contentElement;
02380   contentElement = doc.documentElement();
02381   CHECK( contentElement.isNull(), false );
02382   CHECK( contentElement.isElement(), true );
02383   CHECK( contentElement.localName(), QString("document-content") );
02384   
02385   long totalCellCount = 0;
02386   
02387   KoXmlElement bodyElement;
02388   forEachElement( bodyElement, contentElement )
02389   {
02390     // <office:body>
02391     if( bodyElement.localName() != QString("body") )
02392       continue;
02393       
02394     // now we iterate inside the body
02395     timer.start();
02396       
02397     // <office:spreadsheet>
02398     KoXmlElement spreadsheetElement;
02399     spreadsheetElement = bodyElement.firstChild().toElement();
02400     CHECK( spreadsheetElement.isNull(), false );
02401     CHECK( spreadsheetElement.isElement(), true );
02402     CHECK( spreadsheetElement.localName(), QString("spreadsheet") );
02403     
02404     // now we visit every sheet
02405     long tableCount = -1;
02406     KoXmlElement tableElement;
02407     tableElement = spreadsheetElement.firstChild().toElement();
02408     for(;;)
02409     {
02410         if( tableElement.isNull() ) 
02411           break;
02412           
02413         if( tableElement.localName() != QString("table") )
02414         {
02415           tableElement = tableElement.nextSibling().toElement();
02416           continue;
02417         }  
02418         
02419         QString tableName = tableElement.attributeNS(tableNS,"name","");
02420         tableCount++;  
02421     
02422         printf( " sheet #%ld (%s): ", tableCount+1, qPrintable(tableName) );
02423     
02424         // use to preload everything in this sheet, will slow it down!
02425         // KoXml::load( tableElement, 50 );
02426         
02427         long rowCount = -1;
02428         long cellCount = -1;
02429         
02430         KoXmlElement rowElement;
02431         rowElement = tableElement.firstChild().toElement();
02432         for(;;)
02433         {
02434           if( rowElement.isNull() )
02435             break;
02436             
02437           if( rowElement.localName() != QString("table-row") )
02438           {
02439             rowElement = rowElement.nextSibling().toElement();
02440             continue;
02441           }
02442             
02443           rowCount++;   
02444           KoXml::load( rowElement, 4 );
02445             
02446           CHECK( rowElement.isElement(), true );
02447           CHECK( rowElement.localName(), QString("table-row") );
02448           CHECK( rowElement.parentNode().isNull(), false );
02449           CHECK( rowElement.parentNode()==tableElement, true );
02450     
02451           KoXmlElement cellElement;
02452           cellElement = rowElement.firstChild().toElement();
02453           for( ; ; )
02454           {
02455             if( cellElement.isNull() )
02456               break;
02457             
02458             if( cellElement.localName() != QString("table-cell") )
02459             {
02460               cellElement = cellElement.nextSibling().toElement();
02461               continue;
02462             }
02463             
02464             cellCount++;
02465             
02466             CHECK( cellElement.isNull(), false );
02467             CHECK( cellElement.isElement(), true );
02468             CHECK( cellElement.localName(), QString("table-cell") );
02469             QString text1 = cellElement.text();
02470             QString text2 = cellElement.text();
02471             CHECK( text1, text2 );
02472             QString type1 = cellElement.attributeNS(officeNS,"value-type",QString());
02473             QString type2 = cellElement.attributeNS(officeNS,"value-type",QString());
02474             CHECK( type1, type2 );
02475             QString style1 = cellElement.attributeNS(tableNS,"style-name",QString());
02476             QString style2 = cellElement.attributeNS(tableNS,"style-name",QString());
02477             CHECK( style1, style2 );
02478             
02479             CHECK( cellElement.parentNode().isNull(), false );
02480             CHECK( cellElement.parentNode()==rowElement, true );
02481             
02482             cellElement = cellElement.nextSibling().toElement();
02483           }
02484     
02485     
02486           // better not to unload, freeing memory takes time
02487           KoXml::unload( rowElement );
02488     
02489           rowElement = rowElement.nextSibling().toElement();
02490         }
02491             
02492         printf( " %ld rows, %ld cells\n", rowCount+1, cellCount+1 );
02493         totalCellCount += (cellCount + 1);
02494     
02495         // IMPORTANT: helps minimizing memory usage !!
02496         // we do not need that element anymore, so just throw it away
02497         KoXml::unload( tableElement );
02498         
02499         tableElement = tableElement.nextSibling().toElement();
02500     }
02501     
02502     KoXml::unload( spreadsheetElement );
02503   }
02504   
02505   printf("Total number of cells: %ld\n", totalCellCount);
02506   
02507   int elapsed = timer.elapsed();
02508   printf("External spreadsheet: iterating time is %d ms\n", elapsed );
02509   if( elapsed > 0 )
02510     printf("  approx. %ld cells/second\n", totalCellCount*1000/elapsed);
02511   
02512   // uncomment to check the XML
02513   xmlfile.remove();
02514 }
02515 
02516 int main( int argc, char** argv )
02517 {
02518   if( argc < 2 )
02519   {
02520     testNode();
02521     testElement();
02522     testAttributes();
02523     testText();
02524     testCDATA();
02525     testDocument();
02526     testNamespace();
02527     
02528     testParseQString();
02529 
02530     testUnload();
02531     
02532     testSimpleXML();
02533     testRootError();
02534     testMismatchedTag();
02535     
02536     testConvertQDomElement();
02537     
02538     testSimpleOpenDocumentText();
02539     testSimpleOpenDocumentSpreadsheet();
02540     testSimpleOpenDocumentPresentation();
02541     testSimpleOpenDocumentFormula();
02542   
02543     //testLargeOpenDocumentSpreadsheet();
02544   }
02545   else
02546   {
02547     QString fname( argv[1] );
02548     testExternalOpenDocumentSpreadsheet( fname );
02549   }  
02550 
02551 #ifdef KOXML_USE_QDOM
02552   printf("Using QDom: ");
02553 #else
02554   printf("Using KoXml: ");
02555 #endif
02556   printf("%d tests, %d failed\n", testCount, testFailed );
02557 
02558   return testFailed;
02559 }

Généré le Wed Nov 22 23:41:14 2006 pour KPlato par  doxygen 1.5.1-p1