You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kofficecore/tests/koxmlreadertest.cpp

2075 lines
83 KiB

/* This file is part of the KDE project
Copyright (C) 2005 Ariya Hidayat <ariya@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
*/
// xmlreadertest.cpp - test KoXml classes
// Ariya Hidayat, November 2005
#include <tqstring.h>
#include <tqcstring.h>
#include <tqbuffer.h>
#include <tqtextstream.h>
#include <tqdatetime.h>
#include <tqfile.h>
#include "KoXmlReader.h"
#include <tqxml.h>
#define CHECK(x,y) check(__FILE__,__LINE__,#x,x,y)
static int testCount = 0;
static int testFailed = 0;
template<typename T>
void check( const char *file, int line, const char* msg,
const T& result, const T& expected )
{
testCount++;
if( result != expected )
{
testFailed++;
TQString message;
TQTextStream ts( &message, IO_WriteOnly );
ts << msg;
ts << " Result:";
ts << result;
ts << ", ";
ts << "Expected:";
ts << expected;
printf( "%s [%d]: %s\n", file, line, message.latin1() );
}
}
void check( const char *file, int line, const char* msg, bool result,
bool expected )
{
testCount++;
if( result != expected )
{
testFailed++;
TQString message;
TQTextStream ts( &message, IO_WriteOnly );
ts << msg;
ts << " Result: ";
if( result ) ts << "True"; else ts << "False";
ts << ", ";
ts << "Expected: ";
if( expected ) ts << "True"; else ts << "False";
printf( "%s [%d]: %s\n", file, line, message.latin1() );
}
}
void testNode()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<earth>";
xmlstream << "<continents>";
xmlstream << "<asia/>";
xmlstream << "<africa/>";
xmlstream << "<europe/>";
xmlstream << "<america/>";
xmlstream << "<australia/>";
xmlstream << "<antartic/>";
xmlstream << "</continents>";
xmlstream << "<oceans>";
xmlstream << "<pacific/>";
xmlstream << "<atlantic/>";
xmlstream << "</oceans>";
xmlstream << "</earth>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// null node
KoXmlNode node1;
CHECK( node1.nodeName(), TQString() );
CHECK( node1.isNull(), true );
CHECK( node1.isElement(), false );
CHECK( node1.isElement(), false );
CHECK( node1.isDocument(), false );
CHECK( node1.ownerDocument().isNull(), false );
CHECK( node1.parentNode().isNull(), true );
CHECK( node1.hasChildNodes(), false );
CHECK( node1.firstChild().isNull(), true );
CHECK( node1.lastChild().isNull(), true );
CHECK( node1.previousSibling().isNull(), true );
CHECK( node1.nextSibling().isNull(), true );
// compare with another null node
KoXmlNode node2;
CHECK( node2.isNull(), true );
CHECK( node1==node2, true );
CHECK( node1!=node2, false );
// a node which is a document
KoXmlNode node3 = doc;
CHECK( node3.nodeName(), TQString("#document") );
CHECK( node3.isNull(), false );
CHECK( node3.isElement(), false );
CHECK( node3.isText(), false );
CHECK( node3.isDocument(), true );
CHECK( node3.ownerDocument().isNull(), false );
CHECK( node3.ownerDocument()==doc, true );
CHECK( node3.toDocument()==doc, true );
// convert to document and the compare
KoXmlDocument doc2 = node3.toDocument();
CHECK( doc2.nodeName(), TQString("#document") );
CHECK( doc2.isNull(), false );
CHECK( doc2.isDocument(), true );
CHECK( node3==doc2, true );
// a document is of course can't be converted to element
KoXmlElement invalidElement = node3.toElement();
CHECK( invalidElement.nodeName(), TQString() );
CHECK( invalidElement.isNull(), true );
CHECK( invalidElement.isElement(), true );
CHECK( invalidElement.isText(), false );
CHECK( invalidElement.isDocument(), false );
// clear() makes it a null node again
node3.clear();
CHECK( node3.isNull(), true );
CHECK( node3.nodeName(), TQString() );
CHECK( node3.isElement(), false );
CHECK( node3.isText(), false );
CHECK( node3.isDocument(), false );
CHECK( node3.ownerDocument().isNull(), false );
CHECK( node1==node3, true );
CHECK( node1!=node3, false );
// a node which is an element for <earth>
KoXmlNode node4 = doc.firstChild();
CHECK( node4.isNull(), false );
CHECK( node4.isElement(), true );
CHECK( node4.isText(), false );
CHECK( node4.isDocument(), false );
CHECK( node4.hasChildNodes(), true );
CHECK( node4.ownerDocument()==doc, true );
CHECK( node4.toElement()==doc.firstChild().toElement(), true );
// clear() makes it a null node again
node4.clear();
CHECK( node4.isNull(), true );
CHECK( node4.isElement(), false );
CHECK( node4.isText(), false );
CHECK( node4.isDocument(), false );
CHECK( node4==node1, true );
CHECK( node4!=node1, false );
// a node which is an element for <continents>
KoXmlNode node5 = doc.firstChild().firstChild();
CHECK( node5.nodeName(), TQString("continents") );
CHECK( node5.isNull(), false );
CHECK( node5.isElement(), true );
CHECK( node5.isText(), false );
CHECK( node5.isDocument(), false );
CHECK( node5.hasChildNodes(), true );
CHECK( node5.ownerDocument()==doc, true );
// convert to element and the compare
KoXmlElement continentsElement = node5.toElement();
CHECK( node5==continentsElement, true );
CHECK( continentsElement.isNull(), false );
CHECK( continentsElement.isElement(), true );
CHECK( continentsElement.isText(), false );
CHECK( continentsElement.hasChildNodes(), true );
CHECK( continentsElement.ownerDocument()==doc, true );
// and it doesn't make sense to convert that node to document
// (instead a brand new document is created, i.e. not a null node)
KoXmlDocument invalidDoc = node5.toDocument();
CHECK( invalidDoc.isNull(), false );
CHECK( invalidDoc.isElement(), false );
CHECK( invalidDoc.isText(), false );
CHECK( invalidDoc.isDocument(), true );
// node for <europe> using namedItem() function
KoXmlNode europeNode = continentsElement.namedItem( TQString("europe") );
CHECK( europeNode.nodeName(), TQString("europe") );
CHECK( europeNode.isNull(), false );
CHECK( europeNode.isElement(), true );
CHECK( europeNode.isText(), false );
CHECK( europeNode.hasChildNodes(), false );
CHECK( europeNode.ownerDocument()==doc, true );
// search non-existing node
KoXmlNode fooNode = continentsElement.namedItem( TQString("foobar") );
CHECK( fooNode.isNull(), true );
CHECK( fooNode.isElement(), false );
CHECK( fooNode.isText(), false );
CHECK( fooNode.isCDATASection(), false );
}
void testElement()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<html>";
xmlstream << "<body bgcolor=\"#000\">";
xmlstream << "<p>";
xmlstream << "Hello, world!";
xmlstream << "</p>";
xmlstream << "</body>";
xmlstream << "</html>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// element for <html>
KoXmlElement rootElement;
rootElement = doc.documentElement();
CHECK( rootElement.nodeName(), TQString("html") );
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.isDocument(), false );
CHECK( rootElement.ownerDocument().isNull(), false );
CHECK( rootElement.ownerDocument()==doc, true );
CHECK( rootElement.parentNode().isNull(), false );
CHECK( rootElement.parentNode().toDocument()==doc, true );
CHECK( rootElement.hasChildNodes(), true );
CHECK( rootElement.tagName(), TQString("html") );
CHECK( rootElement.prefix().isNull(), true );
// element for <body>
KoXmlElement bodyElement;
bodyElement = rootElement.firstChild().toElement();
CHECK( bodyElement.nodeName(), TQString("body") );
CHECK( bodyElement.isNull(), false );
CHECK( bodyElement.isElement(), true );
CHECK( bodyElement.isDocument(), false );
CHECK( bodyElement.ownerDocument().isNull(), false );
CHECK( bodyElement.ownerDocument()==doc, true );
CHECK( bodyElement.parentNode().isNull(), false );
CHECK( bodyElement.parentNode()==rootElement, true );
CHECK( bodyElement.hasChildNodes(), true );
CHECK( bodyElement.tagName(), TQString("body") );
CHECK( bodyElement.prefix().isNull(), true );
CHECK( bodyElement.hasAttribute("bgcolor"), true );
CHECK( bodyElement.attribute("bgcolor"), TQString("#000") );
// a shared copy of <body>, will still have access to attribute bgcolor
KoXmlElement body2Element;
body2Element = bodyElement;
CHECK( body2Element.nodeName(), TQString("body") );
CHECK( body2Element.isNull(), false );
CHECK( body2Element.isElement(), true );
CHECK( body2Element.isDocument(), false );
CHECK( body2Element.ownerDocument().isNull(), false );
CHECK( body2Element.ownerDocument()==doc, true );
CHECK( body2Element==bodyElement, true );
CHECK( body2Element!=bodyElement, false );
CHECK( body2Element.hasChildNodes(), true );
CHECK( body2Element.tagName(), TQString("body") );
CHECK( body2Element.prefix().isNull(), true );
CHECK( body2Element.hasAttribute("bgcolor"), true );
CHECK( body2Element.attribute("bgcolor"), TQString("#000") );
// empty element, by default constructor
KoXmlElement testElement;
CHECK( testElement.nodeName(), TQString() );
CHECK( testElement.isNull(), true );
CHECK( testElement.isElement(), true );
CHECK( testElement.isDocument(), false );
CHECK( testElement.ownerDocument().isNull(), false );
CHECK( testElement.ownerDocument()!=doc, true );
CHECK( testElement==rootElement, false );
CHECK( testElement!=rootElement, true );
CHECK( testElement.parentNode().isNull(), true );
CHECK( testElement.hasChildNodes(), false );
// check assignment operator
testElement = rootElement;
CHECK( testElement.nodeName(), TQString("html") );
CHECK( testElement.isNull(), false );
CHECK( testElement.isElement(), true );
CHECK( testElement.isDocument(), false );
CHECK( testElement==rootElement, true );
CHECK( testElement!=rootElement, false );
CHECK( testElement.parentNode().isNull(), false );
CHECK( testElement.parentNode().toDocument()==doc, true );
CHECK( testElement.tagName(), TQString("html") );
CHECK( testElement.prefix().isNull(), true );
// assigned from another empty element
testElement = KoXmlElement();
CHECK( testElement.isNull(), true );
CHECK( testElement!=rootElement, true );
// assigned from <body>
testElement = bodyElement;
CHECK( testElement.isNull(), false );
CHECK( testElement.isElement(), true );
CHECK( testElement.isDocument(), false );
CHECK( testElement.ownerDocument().isNull(), false );
CHECK( testElement.ownerDocument()==doc, true );
CHECK( testElement==bodyElement, true );
CHECK( testElement.parentNode().isNull(), false );
CHECK( testElement.tagName(), TQString("body") );
CHECK( testElement.prefix().isNull(), true );
CHECK( testElement.hasChildNodes(), true );
// copy constructor
KoXmlElement dummyElement( rootElement );
CHECK( dummyElement.isNull(), false );
CHECK( dummyElement.isElement(), true );
CHECK( dummyElement.isDocument(), false );
CHECK( dummyElement.ownerDocument().isNull(), false );
CHECK( dummyElement.ownerDocument()==doc, true );
CHECK( dummyElement==rootElement, true );
CHECK( dummyElement.parentNode().isNull(), false );
CHECK( dummyElement.hasChildNodes(), true );
CHECK( dummyElement.tagName(), TQString("html") );
CHECK( dummyElement.prefix().isNull(), true );
// clear() turns element to null node
dummyElement.clear();
CHECK( dummyElement.isNull(), true );
CHECK( dummyElement.isElement(), true );
CHECK( dummyElement.isDocument(), false );
CHECK( dummyElement.ownerDocument().isNull(), false );
CHECK( dummyElement.ownerDocument()==doc, false );
CHECK( dummyElement.hasChildNodes(), false );
CHECK( dummyElement==rootElement, false );
CHECK( dummyElement!=rootElement, true );
// check for plain null node converted to element
KoXmlNode dummyNode;
dummyElement = dummyNode.toElement();
CHECK( dummyElement.isNull(), true );
CHECK( dummyElement.isElement(), true );
CHECK( dummyElement.isDocument(), false );
CHECK( dummyElement.ownerDocument().isNull(), false );
CHECK( dummyElement.hasChildNodes(), false );
CHECK( dummyElement.ownerDocument()==doc, false );
}
void testAttributes()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<p>";
xmlstream << "<img src=\"foo.png\" width=\"300\" height=\"150\"/>";
xmlstream << "</p>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
KoXmlElement rootElement;
rootElement = doc.documentElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.parentNode().isNull(), false );
CHECK( rootElement.parentNode().toDocument()==doc, true );
CHECK( rootElement.tagName(), TQString("p") );
CHECK( rootElement.prefix().isNull(), true );
KoXmlElement imgElement;
imgElement = rootElement.firstChild().toElement();
CHECK( imgElement.isNull(), false );
CHECK( imgElement.isElement(), true );
CHECK( imgElement.tagName(), TQString("img") );
CHECK( imgElement.prefix().isNull(), true );
CHECK( imgElement.hasAttribute("src"), true );
CHECK( imgElement.hasAttribute("width"), true );
CHECK( imgElement.hasAttribute("height"), true );
CHECK( imgElement.hasAttribute("non-exist"), false );
CHECK( imgElement.hasAttribute("SRC"), false );
CHECK( imgElement.attribute("src"), TQString("foo.png") );
CHECK( imgElement.attribute("width"), TQString("300") );
CHECK( imgElement.attribute("width").toInt(), 300 );
CHECK( imgElement.attribute("height"), TQString("150") );
CHECK( imgElement.attribute("height").toInt(), 150 );
CHECK( imgElement.attribute("border").isEmpty(), true );
CHECK( imgElement.attribute("border","0").toInt(), 0 );
CHECK( imgElement.attribute("border","-1").toInt(), -1 );
}
void testText()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<p>";
xmlstream << "Hello ";
xmlstream << "<b>world</b>";
xmlstream << "</p>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// element for <p>
KoXmlElement parElement;
parElement = doc.documentElement();
CHECK( parElement.isNull(), false );
CHECK( parElement.isElement(), true );
CHECK( parElement.isText(), false );
CHECK( parElement.isDocument(), false );
CHECK( parElement.ownerDocument().isNull(), false );
CHECK( parElement.ownerDocument()==doc, true );
CHECK( parElement.parentNode().isNull(), false );
CHECK( parElement.parentNode().toDocument()==doc, true );
CHECK( parElement.hasChildNodes(), true );
CHECK( parElement.tagName(), TQString("p") );
CHECK( parElement.prefix().isNull(), true );
CHECK( parElement.text(), TQString("Hello world") );
// node for "Hello"
KoXmlNode helloNode;
helloNode = parElement.firstChild();
CHECK( helloNode.nodeName(), TQString("#text") );
CHECK( helloNode.isNull(), false );
CHECK( helloNode.isElement(), false );
CHECK( helloNode.isText(), true );
CHECK( helloNode.isDocument(), false );
// "Hello" text
KoXmlText helloText;
helloText = helloNode.toText();
CHECK( helloText.nodeName(), TQString("#text") );
CHECK( helloText.isNull(), false );
CHECK( helloText.isElement(), false );
CHECK( helloText.isText(), true );
CHECK( helloText.isDocument(), false );
CHECK( helloText.data(), TQString("Hello ") );
// shared copy of the text
KoXmlText hello2Text;
hello2Text = helloText;
CHECK( hello2Text.isNull(), false );
CHECK( hello2Text.isElement(), false );
CHECK( hello2Text.isText(), true );
CHECK( hello2Text.isDocument(), false );
CHECK( hello2Text.data(), TQString("Hello ") );
// element for <b>
KoXmlElement boldElement;
boldElement = helloNode.nextSibling().toElement();
CHECK( boldElement.isNull(), false );
CHECK( boldElement.isElement(), true );
CHECK( boldElement.isText(), false );
CHECK( boldElement.isDocument(), false );
CHECK( boldElement.ownerDocument().isNull(), false );
CHECK( boldElement.ownerDocument()==doc, true );
CHECK( boldElement.parentNode().isNull(), false );
CHECK( boldElement.hasChildNodes(), true );
CHECK( boldElement.tagName(), TQString("b") );
CHECK( boldElement.prefix().isNull(), true );
// "world" text
KoXmlText worldText;
worldText = boldElement.firstChild().toText();
CHECK( worldText.isNull(), false );
CHECK( worldText.isElement(), false );
CHECK( worldText.isText(), true );
CHECK( worldText.isDocument(), false );
CHECK( worldText.data(), TQString("world") );
}
void testCDATA()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<p>";
xmlstream << "Hello ";
xmlstream << "<![CDATA[world]]>";
xmlstream << "</p>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// element for <p>
KoXmlElement parElement;
parElement = doc.documentElement();
CHECK( parElement.isNull(), false );
CHECK( parElement.isElement(), true );
CHECK( parElement.isText(), false );
CHECK( parElement.isDocument(), false );
CHECK( parElement.ownerDocument().isNull(), false );
CHECK( parElement.ownerDocument()==doc, true );
CHECK( parElement.parentNode().isNull(), false );
CHECK( parElement.parentNode().toDocument()==doc, true );
CHECK( parElement.hasChildNodes(), true );
CHECK( parElement.tagName(), TQString("p") );
CHECK( parElement.prefix().isNull(), true );
CHECK( parElement.text(), TQString("Hello world") );
// node for "Hello"
KoXmlNode helloNode;
helloNode = parElement.firstChild();
CHECK( helloNode.isNull(), false );
CHECK( helloNode.isElement(), false );
CHECK( helloNode.isText(), true );
CHECK( helloNode.isDocument(), false );
// "Hello" text
KoXmlText helloText;
helloText = helloNode.toText();
CHECK( helloText.isNull(), false );
CHECK( helloText.isElement(), false );
CHECK( helloText.isText(), true );
CHECK( helloText.isDocument(), false );
CHECK( helloText.data(), TQString("Hello ") );
// node for CDATA "world!"
// Note: isText() is also true for CDATA
KoXmlNode worldNode;
worldNode = helloNode.nextSibling();
CHECK( worldNode.nodeName(), TQString("#cdata-section") );
CHECK( worldNode.isNull(), false );
CHECK( worldNode.isElement(), false );
CHECK( worldNode.isText(), true );
CHECK( worldNode.isCDATASection(), true );
CHECK( worldNode.isDocument(), false );
// CDATA section for "world!"
// Note: isText() is also true for CDATA
KoXmlCDATASection worldCDATA;
worldCDATA = worldNode.toCDATASection();
CHECK( worldCDATA.nodeName(), TQString("#cdata-section") );
CHECK( worldCDATA.isNull(), false );
CHECK( worldCDATA.isElement(), false );
CHECK( worldCDATA.isText(), true );
CHECK( worldCDATA.isCDATASection(), true );
CHECK( worldCDATA.isDocument(), false );
CHECK( worldCDATA.data(), TQString("world") );
}
void testDocument()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<koffice>";
xmlstream << " <kword/>\n";
xmlstream << " <kpresenter/>\n";
xmlstream << " <chalk/>\n";
xmlstream << "</koffice>";
KoXmlDocument doc;
// empty document
CHECK( doc.nodeName(), TQString("#document") );
CHECK( doc.isNull(), false );
CHECK( doc.isElement(), false );
CHECK( doc.isDocument(), true );
CHECK( doc.parentNode().isNull(), true );
CHECK( doc.firstChild().isNull(), true );
CHECK( doc.lastChild().isNull(), true );
CHECK( doc.previousSibling().isNull(), true );
CHECK( doc.nextSibling().isNull(), true );
// now give something as the content
CHECK( doc.setContent(&xmldevice,&errorMsg,&errorLine,&errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// this document has something already
CHECK( doc.nodeName(), TQString("#document") );
CHECK( doc.isNull(), false );
CHECK( doc.isElement(), false );
CHECK( doc.isDocument(), true );
CHECK( doc.parentNode().isNull(), true );
CHECK( doc.firstChild().isNull(), false );
CHECK( doc.lastChild().isNull(), false );
CHECK( doc.previousSibling().isNull(), true );
CHECK( doc.nextSibling().isNull(), true );
// make sure its children are fine
KoXmlElement rootElement;
rootElement = doc.firstChild().toElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.isDocument(), false );
CHECK( rootElement.parentNode().isNull(), false );
CHECK( rootElement.parentNode().toDocument()==doc, true );
rootElement = doc.lastChild().toElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.isDocument(), false );
CHECK( rootElement.parentNode().isNull(), false );
CHECK( rootElement.parentNode().toDocument()==doc, true );
// clear() converts it into null node
doc.clear();
CHECK( doc.nodeName(), TQString() );
CHECK( doc.isNull(), true );
CHECK( doc.isElement(), false );
CHECK( doc.isDocument(), true );
CHECK( doc.parentNode().isNull(), true );
CHECK( doc.firstChild().isNull(), true );
CHECK( doc.lastChild().isNull(), true );
CHECK( doc.previousSibling().isNull(), true );
CHECK( doc.nextSibling().isNull(), true );
// assigned from another empty document
doc = KoXmlDocument();
CHECK( doc.nodeName(), TQString("#document") );
CHECK( doc.isNull(), false );
CHECK( doc.isElement(), false );
CHECK( doc.isDocument(), true );
CHECK( doc.parentNode().isNull(), true );
}
void testNamespace()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// taken from example in TQt documentation (xml.html)
xmlstream << "<document xmlns:book = \"http://trolltech.com/fnord/book/\"";
xmlstream << " xmlns = \"http://trolltech.com/fnord/\" >";
xmlstream << "<book>";
xmlstream << " <book:title>Practical XML</book:title>";
xmlstream << " <book:author xmlns:fnord = \"http://trolltech.com/fnord/\"";
xmlstream << " title=\"Ms\"";
xmlstream << " fnord:title=\"Goddess\"";
xmlstream << " name=\"Eris Kallisti\"/>";
xmlstream << " <chapter>";
xmlstream << " <title>A Namespace Called fnord</title>";
xmlstream << " </chapter>";
xmlstream << "</book>";
xmlstream << "</document>";
KoXmlDocument doc;
KoXmlElement rootElement;
KoXmlElement bookElement;
KoXmlElement bookTitleElement;
KoXmlElement bookAuthorElement;
// ------------- first without any namespace processing -----------
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
rootElement = doc.documentElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.tagName(), TQString("document") );
CHECK( rootElement.prefix().isNull(), true );
bookElement = rootElement.firstChild().toElement();
CHECK( bookElement.isNull(), false );
CHECK( bookElement.isElement(), true );
CHECK( bookElement.tagName(), TQString("book") );
CHECK( bookElement.prefix().isNull(), true );
CHECK( bookElement.localName(), TQString() );
bookTitleElement = bookElement.firstChild().toElement();
CHECK( bookTitleElement.isNull(), false );
CHECK( bookTitleElement.isElement(), true );
CHECK( bookTitleElement.tagName(), TQString("book:title") );
CHECK( bookTitleElement.prefix().isNull(), true );
CHECK( bookTitleElement.localName(), TQString() );
bookAuthorElement = bookTitleElement.nextSibling().toElement();
CHECK( bookAuthorElement.isNull(), false );
CHECK( bookAuthorElement.isElement(), true );
CHECK( bookAuthorElement.tagName(), TQString("book:author") );
CHECK( bookAuthorElement.prefix().isNull(), true );
CHECK( bookAuthorElement.attribute("title"), TQString("Ms") );
CHECK( bookAuthorElement.attribute("fnord:title"), TQString("Goddess") );
CHECK( bookAuthorElement.attribute("name"), TQString("Eris Kallisti") );
// ------------- now with namespace processing -----------
xmldevice.at(0); // just to rewind
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
char* defaultNS = "http://trolltech.com/fnord/";
char* bookNS = "http://trolltech.com/fnord/book/";
char* fnordNS = "http://trolltech.com/fnord/";
// <document>
rootElement = doc.documentElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.tagName(), TQString("document") );
CHECK( rootElement.prefix().isEmpty(), true );
CHECK( rootElement.namespaceURI(), TQString( defaultNS ) );
CHECK( rootElement.localName(), TQString("document") );
// <book>
bookElement = rootElement.firstChild().toElement();
CHECK( bookElement.isNull(), false );
CHECK( bookElement.isElement(), true );
CHECK( bookElement.tagName(), TQString("book") );
CHECK( bookElement.prefix().isEmpty(), true );
CHECK( bookElement.namespaceURI(), TQString( defaultNS ) );
CHECK( bookElement.localName(), TQString("book") );
// <book:title>
bookTitleElement = bookElement.firstChild().toElement();
CHECK( bookTitleElement.isNull(), false );
CHECK( bookTitleElement.isElement(), true );
CHECK( bookTitleElement.tagName(), TQString("title") );
CHECK( bookTitleElement.prefix(), TQString("book") );
CHECK( bookTitleElement.namespaceURI(), TQString(bookNS) );
CHECK( bookTitleElement.localName(), TQString("title") );
// another way, find it using namedItemNS()
KoXmlElement book2TitleElement;
book2TitleElement = KoXml::namedItemNS( rootElement.firstChild(), bookNS, "title" );
//book2TitleElement = bookElement.namedItemNS( bookNS, "title" ).toElement();
CHECK( book2TitleElement==bookTitleElement, true );
CHECK( book2TitleElement.isNull(), false );
CHECK( book2TitleElement.isElement(), true );
CHECK( book2TitleElement.tagName(), TQString("title") );
// <book:author>
bookAuthorElement = bookTitleElement.nextSibling().toElement();
CHECK( bookAuthorElement.isNull(), false );
CHECK( bookAuthorElement.isElement(), true );
CHECK( bookAuthorElement.tagName(), TQString("author") );
CHECK( bookAuthorElement.prefix(), TQString("book") );
CHECK( bookAuthorElement.namespaceURI(), TQString(bookNS) );
CHECK( bookAuthorElement.localName(), TQString("author") );
// another way, find it using namedItemNS()
KoXmlElement book2AuthorElement;
book2AuthorElement = KoXml::namedItemNS( bookElement, bookNS, "author" );
//book2AuthorElement = bookElement.namedItemNS( bookNS, "author" ).toElement();
CHECK( book2AuthorElement==bookAuthorElement, true );
CHECK( book2AuthorElement.isNull(), false );
CHECK( book2AuthorElement.isElement(), true );
CHECK( book2AuthorElement.tagName(), TQString("author") );
// attributes in <book:author>
// Note: with namespace processing, attribute's prefix is taken out and
// hence "fnord:title" will simply override "title"
// and searching attribute with prefix will give no result
CHECK( bookAuthorElement.hasAttribute("title"), true );
CHECK( bookAuthorElement.hasAttribute("fnord:title"), false );
CHECK( bookAuthorElement.hasAttribute("name"), true );
CHECK( bookAuthorElement.attribute("title"), TQString("Goddess") );
CHECK( bookAuthorElement.attribute("fnord:title").isEmpty(), true );
CHECK( bookAuthorElement.attribute("name"), TQString("Eris Kallisti") );
// attributes in <book:author>, with NS family of functions
// those without prefix are not accessible at all, because they do not belong
// to any namespace at all.
// Note: default namespace does not apply to attribute names!
CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"title"), true );
CHECK( bookAuthorElement.hasAttributeNS(bookNS,"title"), false );
CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"title"), true );
CHECK( bookAuthorElement.attributeNS(defaultNS,"title",""), TQString("Goddess") );
CHECK( bookAuthorElement.attributeNS(bookNS,"title",""), TQString("") );
CHECK( bookAuthorElement.attributeNS(fnordNS,"title",""), TQString("Goddess") );
CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"fnord:title"), false );
CHECK( bookAuthorElement.hasAttributeNS(bookNS,"fnord:title"), false );
CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"fnord:title"), false );
CHECK( bookAuthorElement.hasAttributeNS(defaultNS,"name"), false );
CHECK( bookAuthorElement.hasAttributeNS(bookNS,"name"), false );
CHECK( bookAuthorElement.hasAttributeNS(fnordNS,"name"), false );
CHECK( bookAuthorElement.attributeNS(defaultNS,"name",TQString()).isEmpty(), true );
CHECK( bookAuthorElement.attributeNS(bookNS,"name",TQString()).isEmpty(), true );
CHECK( bookAuthorElement.attributeNS(fnordNS,"name",TQString()).isEmpty(), true );
}
void testUnload()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<earth>";
xmlstream << "<continents>";
xmlstream << "<asia/>";
xmlstream << "<africa/>";
xmlstream << "<europe/>";
xmlstream << "<america/>";
xmlstream << "<australia/>";
xmlstream << "<antartic/>";
xmlstream << "</continents>";
xmlstream << "<oceans>";
xmlstream << "<pacific/>";
xmlstream << "<atlantic/>";
xmlstream << "</oceans>";
xmlstream << "</earth>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
KoXmlElement earthElement;
earthElement = doc.documentElement().toElement();
CHECK( earthElement.isNull(), false );
CHECK( earthElement.isElement(), true );
CHECK( earthElement.parentNode().isNull(), false );
CHECK( earthElement.hasChildNodes(), true );
CHECK( earthElement.tagName(), TQString("earth") );
CHECK( earthElement.prefix().isNull(), true );
// this ensures that all child nodes of <earth> are loaded
earthElement.firstChild();
// explicitly unload all child nodes of <earth>
KoXml::unload( earthElement );
// we should get the correct first child
KoXmlElement continentsElement = earthElement.firstChild().toElement();
CHECK( continentsElement.nodeName(), TQString("continents") );
CHECK( continentsElement.isNull(), false );
CHECK( continentsElement.isElement(), true );
CHECK( continentsElement.isText(), false );
CHECK( continentsElement.isDocument(), false );
CHECK( continentsElement.hasChildNodes(), true );
// let us unload everything again
KoXml::unload( earthElement );
// we should get the correct last child
KoXmlElement oceansElement = earthElement.lastChild().toElement();
CHECK( oceansElement.nodeName(), TQString("oceans") );
CHECK( oceansElement.isNull(), false );
CHECK( oceansElement.isElement(), true );
CHECK( oceansElement.isText(), false );
CHECK( oceansElement.isDocument(), false );
CHECK( oceansElement.hasChildNodes(), true );
}
void testSimpleXML()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<solarsystem>";
xmlstream << " <mercurius/>\n";
xmlstream << " <venus/>\n";
xmlstream << " <earth>\n";
xmlstream << " <moon/>\n";
xmlstream << " </earth>\n";
xmlstream << " <mars/>\n";
xmlstream << " <jupiter/>\n";
xmlstream << "</solarsystem>";
KoXmlDocument doc;
CHECK( doc.setContent(&xmldevice,&errorMsg,&errorLine,&errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
// <solarsystem>
KoXmlElement rootElement;
rootElement = doc.documentElement();
CHECK( rootElement.isNull(), false );
CHECK( rootElement.isElement(), true );
CHECK( rootElement.parentNode().isNull(), false );
CHECK( rootElement.hasChildNodes(), true );
CHECK( rootElement.tagName(), TQString("solarsystem") );
CHECK( rootElement.prefix().isNull(), true );
// node <mercurius>
KoXmlNode firstPlanetNode;
firstPlanetNode = rootElement.firstChild();
CHECK( firstPlanetNode.isNull(), false );
CHECK( firstPlanetNode.isElement(), true );
CHECK( firstPlanetNode.nextSibling().isNull(), false );
CHECK( firstPlanetNode.previousSibling().isNull(), true );
CHECK( firstPlanetNode.parentNode().isNull(), false );
CHECK( firstPlanetNode.parentNode()==rootElement, true );
CHECK( firstPlanetNode.parentNode()!=rootElement, false );
CHECK( firstPlanetNode.hasChildNodes(), false );
CHECK( firstPlanetNode.firstChild().isNull(), true );
CHECK( firstPlanetNode.lastChild().isNull(), true );
// element <mercurius>
KoXmlElement firstPlanetElement;
firstPlanetElement = firstPlanetNode.toElement();
CHECK( firstPlanetElement.isNull(), false );
CHECK( firstPlanetElement.isElement(), true );
CHECK( firstPlanetElement.parentNode().isNull(), false );
CHECK( firstPlanetElement.parentNode()==rootElement, true );
CHECK( firstPlanetElement.hasChildNodes(), false );
CHECK( firstPlanetElement.firstChild().isNull(), true );
CHECK( firstPlanetElement.lastChild().isNull(), true );
CHECK( firstPlanetElement.tagName(), TQString("mercurius") );
CHECK( firstPlanetElement.prefix().isNull(), true );
// node <venus>
KoXmlNode secondPlanetNode;
secondPlanetNode = firstPlanetNode.nextSibling();
CHECK( secondPlanetNode.isNull(), false );
CHECK( secondPlanetNode.isElement(), true );
CHECK( secondPlanetNode.nextSibling().isNull(), false );
CHECK( secondPlanetNode.previousSibling().isNull(), false );
CHECK( secondPlanetNode.previousSibling()==firstPlanetNode, true );
CHECK( secondPlanetNode.previousSibling()==firstPlanetElement, true );
CHECK( secondPlanetNode.parentNode().isNull(), false );
CHECK( secondPlanetNode.parentNode()==rootElement, true );
CHECK( secondPlanetNode.parentNode()!=rootElement, false );
CHECK( secondPlanetNode.hasChildNodes(), false );
CHECK( secondPlanetNode.firstChild().isNull(), true );
CHECK( secondPlanetNode.lastChild().isNull(), true );
// element <venus>
KoXmlElement secondPlanetElement;
secondPlanetElement = secondPlanetNode.toElement();
CHECK( secondPlanetElement.isNull(), false );
CHECK( secondPlanetElement.isElement(), true );
CHECK( secondPlanetElement.nextSibling().isNull(), false );
CHECK( secondPlanetElement.previousSibling().isNull(), false );
CHECK( secondPlanetElement.previousSibling()==firstPlanetNode, true );
CHECK( secondPlanetElement.previousSibling()==firstPlanetElement, true );
CHECK( secondPlanetElement.parentNode().isNull(), false );
CHECK( secondPlanetElement.parentNode()==rootElement, true );
CHECK( secondPlanetElement.parentNode()!=rootElement, false );
CHECK( secondPlanetElement.hasChildNodes(), false );
CHECK( secondPlanetElement.firstChild().isNull(), true );
CHECK( secondPlanetElement.lastChild().isNull(), true );
CHECK( secondPlanetElement.tagName(), TQString("venus") );
CHECK( secondPlanetElement.prefix().isNull(), true );
}
void testRootError()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
// multiple root nodes are not valid !
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<earth></earth><moon></moon>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), false );
CHECK( errorMsg.isEmpty(), false );
CHECK( errorMsg, TQString("unexpected character") );
CHECK( errorLine, 1 );
CHECK( errorColumn, 17 );
}
void testMismatchedTag()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
xmlstream << "<earth></e>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, &errorMsg, &errorLine, &errorColumn ), false );
CHECK( errorMsg.isEmpty(), false );
CHECK( errorMsg, TQString("tag mismatch") );
CHECK( errorLine, 1 );
CHECK( errorColumn, 11 );
}
void testSimpleOpenDocumentText()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// content.xml from a simple OpenDocument text
// it has only paragraph "Hello, world!"
// automatic styles, declarations and unnecessary namespaces are omitted.
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content ";
xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
xmlstream << " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"";
xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
xmlstream << " office:version=\"1.0\">";
xmlstream << " <office:automatic-styles/>";
xmlstream << " <office:body>";
xmlstream << " <office:text>";
xmlstream << " <text:p text:style-name=\"Standard\">Hello, world!</text:p>";
xmlstream << " </office:text>";
xmlstream << " </office:body>";
xmlstream << "</office:document-content>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
// <office:document-content>
KoXmlElement contentElement;
contentElement = doc.documentElement();
CHECK( contentElement.isNull(), false );
CHECK( contentElement.isElement(), true );
CHECK( contentElement.parentNode().isNull(), false );
CHECK( contentElement.parentNode().toDocument()==doc, true );
CHECK( contentElement.firstChild().isNull(), false );
CHECK( contentElement.lastChild().isNull(), false );
CHECK( contentElement.previousSibling().isNull(), false );
CHECK( contentElement.nextSibling().isNull(), true );
CHECK( contentElement.localName(), TQString("document-content") );
CHECK( contentElement.hasAttributeNS(officeNS,"version"), true );
CHECK( contentElement.attributeNS(officeNS,"version",""), TQString("1.0") );
// <office:automatic-styles>
KoXmlElement stylesElement;
stylesElement = KoXml::namedItemNS( contentElement, officeNS, "automatic-styles" );
CHECK( stylesElement.isNull(), false );
CHECK( stylesElement.isElement(), true );
CHECK( stylesElement.parentNode().isNull(), false );
CHECK( stylesElement.parentNode()==contentElement, true );
CHECK( stylesElement.firstChild().isNull(), true );
CHECK( stylesElement.lastChild().isNull(), true );
CHECK( stylesElement.previousSibling().isNull(), true );
CHECK( stylesElement.nextSibling().isNull(), false );
CHECK( stylesElement.localName(), TQString("automatic-styles") );
// also same <office:automatic-styles>, but without namedItemNS
KoXmlNode styles2Element;
styles2Element = contentElement.firstChild().toElement();
CHECK( styles2Element.isNull(), false );
CHECK( styles2Element.isElement(), true );
CHECK( styles2Element.parentNode().isNull(), false );
CHECK( styles2Element.parentNode()==contentElement, true );
CHECK( styles2Element.firstChild().isNull(), true );
CHECK( styles2Element.lastChild().isNull(), true );
CHECK( styles2Element.previousSibling().isNull(), true );
CHECK( styles2Element.nextSibling().isNull(), false );
CHECK( styles2Element.localName(), TQString("automatic-styles") );
// <office:body>
KoXmlElement bodyElement;
bodyElement = KoXml::namedItemNS( contentElement, officeNS, "body" );
CHECK( bodyElement.isNull(), false );
CHECK( bodyElement.isElement(), true );
CHECK( bodyElement.parentNode().isNull(), false );
CHECK( bodyElement.parentNode()==contentElement, true );
CHECK( bodyElement.firstChild().isNull(), false );
CHECK( bodyElement.lastChild().isNull(), false );
CHECK( bodyElement.previousSibling().isNull(), false );
CHECK( bodyElement.nextSibling().isNull(), true );
CHECK( bodyElement.localName(), TQString("body") );
// also same <office:body>, but without namedItemNS
KoXmlElement body2Element;
body2Element = stylesElement.nextSibling().toElement();
CHECK( body2Element.isNull(), false );
CHECK( body2Element.isElement(), true );
CHECK( body2Element.parentNode().isNull(), false );
CHECK( body2Element.parentNode()==contentElement, true );
CHECK( body2Element.firstChild().isNull(), false );
CHECK( body2Element.lastChild().isNull(), false );
CHECK( body2Element.previousSibling().isNull(), false );
CHECK( body2Element.nextSibling().isNull(), true );
CHECK( body2Element.localName(), TQString("body") );
// <office:text>
KoXmlElement textElement;
textElement = KoXml::namedItemNS( bodyElement, officeNS, "text" );
CHECK( textElement.isNull(), false );
CHECK( textElement.isElement(), true );
CHECK( textElement.parentNode().isNull(), false );
CHECK( textElement.parentNode()==bodyElement, true );
CHECK( textElement.firstChild().isNull(), false );
CHECK( textElement.lastChild().isNull(), false );
CHECK( textElement.previousSibling().isNull(), true );
CHECK( textElement.nextSibling().isNull(), true );
CHECK( textElement.localName(), TQString("text") );
// the same <office:text>, but without namedItemNS
KoXmlElement text2Element;
text2Element = bodyElement.firstChild().toElement();
CHECK( text2Element.isNull(), false );
CHECK( text2Element.isElement(), true );
CHECK( text2Element.parentNode().isNull(), false );
CHECK( text2Element.parentNode()==bodyElement, true );
CHECK( text2Element.firstChild().isNull(), false );
CHECK( text2Element.lastChild().isNull(), false );
CHECK( text2Element.previousSibling().isNull(), true );
CHECK( text2Element.nextSibling().isNull(), true );
CHECK( text2Element.localName(), TQString("text") );
// <text:p>
KoXmlElement parElement;
parElement = textElement.firstChild().toElement();
CHECK( parElement.isNull(), false );
CHECK( parElement.isElement(), true );
CHECK( parElement.parentNode().isNull(), false );
CHECK( parElement.parentNode()==textElement, true );
CHECK( parElement.firstChild().isNull(), false );
CHECK( parElement.lastChild().isNull(), false );
CHECK( parElement.previousSibling().isNull(), true );
CHECK( parElement.nextSibling().isNull(), true );
CHECK( parElement.tagName(), TQString("p") );
CHECK( parElement.text(), TQString("Hello, world!") );
CHECK( parElement.attributeNS( TQString(textNS),"style-name",""), TQString("Standard") );
}
void testSimpleOpenDocumentSpreadsheet()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// content.xml from a simple OpenDocument spreadsheet
// the document has three worksheets, the last two are empty.
// on the first sheet, cell A1 contains the text "Hello, world".
// automatic styles, font declarations and unnecessary namespaces are omitted.
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content ";
xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\">";
xmlstream << "<office:body>";
xmlstream << "<office:spreadsheet>";
xmlstream << "<table:table table:name=\"Sheet1\" table:style-name=\"ta1\" table:print=\"false\">";
xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
xmlstream << "<table:table-row table:style-name=\"ro1\">";
xmlstream << "<table:table-cell office:value-type=\"string\">";
xmlstream << "<text:p>Hello, world</text:p>";
xmlstream << "</table:table-cell>";
xmlstream << "</table:table-row>";
xmlstream << "</table:table>";
xmlstream << "<table:table table:name=\"Sheet2\" table:style-name=\"ta1\" table:print=\"false\">";
xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
xmlstream << "<table:table-row table:style-name=\"ro1\">";
xmlstream << "<table:table-cell/>";
xmlstream << "</table:table-row>";
xmlstream << "</table:table>";
xmlstream << "<table:table table:name=\"Sheet3\" table:style-name=\"ta1\" table:print=\"false\">";
xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
xmlstream << "<table:table-row table:style-name=\"ro1\">";
xmlstream << "<table:table-cell/>";
xmlstream << "</table:table-row>";
xmlstream << "</table:table>";
xmlstream << "</office:spreadsheet>";
xmlstream << "</office:body>";
xmlstream << "</office:document-content>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
TQString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
TQString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
TQString textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
// <office:document-content>
KoXmlElement contentElement;
contentElement = doc.documentElement();
CHECK( contentElement.isNull(), false );
CHECK( contentElement.isElement(), true );
CHECK( contentElement.parentNode().isNull(), false );
CHECK( contentElement.parentNode().toDocument()==doc, true );
CHECK( contentElement.firstChild().isNull(), false );
CHECK( contentElement.lastChild().isNull(), false );
CHECK( contentElement.previousSibling().isNull(), false );
CHECK( contentElement.nextSibling().isNull(), true );
CHECK( contentElement.localName(), TQString("document-content") );
// <office:body>
KoXmlElement bodyElement;
bodyElement = contentElement.firstChild().toElement();
CHECK( bodyElement.isNull(), false );
CHECK( bodyElement.isElement(), true );
CHECK( bodyElement.parentNode().isNull(), false );
CHECK( bodyElement.parentNode()==contentElement, true );
CHECK( bodyElement.firstChild().isNull(), false );
CHECK( bodyElement.lastChild().isNull(), false );
CHECK( bodyElement.previousSibling().isNull(), true );
CHECK( bodyElement.nextSibling().isNull(), true );
CHECK( bodyElement.localName(), TQString("body") );
// <office:spreadsheet>
KoXmlElement spreadsheetElement;
spreadsheetElement = bodyElement.firstChild().toElement();
CHECK( spreadsheetElement.isNull(), false );
CHECK( spreadsheetElement.isElement(), true );
CHECK( spreadsheetElement.parentNode().isNull(), false );
CHECK( spreadsheetElement.parentNode()==bodyElement, true );
CHECK( spreadsheetElement.firstChild().isNull(), false );
CHECK( spreadsheetElement.lastChild().isNull(), false );
CHECK( spreadsheetElement.previousSibling().isNull(), true );
CHECK( spreadsheetElement.nextSibling().isNull(), true );
CHECK( spreadsheetElement.localName(), TQString("spreadsheet") );
// <table:table> for Sheet1
KoXmlElement sheet1Element;
sheet1Element = spreadsheetElement.firstChild().toElement();
CHECK( sheet1Element.isNull(), false );
CHECK( sheet1Element.isElement(), true );
CHECK( sheet1Element.parentNode().isNull(), false );
CHECK( sheet1Element.parentNode()==spreadsheetElement, true );
CHECK( sheet1Element.firstChild().isNull(), false );
CHECK( sheet1Element.lastChild().isNull(), false );
CHECK( sheet1Element.previousSibling().isNull(), true );
CHECK( sheet1Element.nextSibling().isNull(), false );
CHECK( sheet1Element.tagName(), TQString("table") );
CHECK( sheet1Element.hasAttributeNS(tableNS,"name"), true );
CHECK( sheet1Element.attributeNS(tableNS,"name",""), TQString("Sheet1") );
CHECK( sheet1Element.attributeNS(tableNS,"style-name",""), TQString("ta1") );
CHECK( sheet1Element.attributeNS(tableNS,"print",""), TQString("false") );
KoXml::load( sheet1Element, 100 );
// <table:table-column>
KoXmlElement columnElement;
columnElement = sheet1Element.firstChild().toElement();
CHECK( columnElement.isNull(), false );
CHECK( columnElement.isElement(), true );
CHECK( columnElement.parentNode().isNull(), false );
CHECK( columnElement.parentNode()==sheet1Element, true );
CHECK( columnElement.firstChild().isNull(), true );
CHECK( columnElement.lastChild().isNull(), true );
CHECK( columnElement.previousSibling().isNull(), true );
CHECK( columnElement.nextSibling().isNull(), false );
CHECK( columnElement.tagName(), TQString("table-column") );
CHECK( columnElement.attributeNS(tableNS,"style-name",""), TQString("co1") );
CHECK( columnElement.attributeNS(tableNS,"default-cell-style-name",""), TQString("Default") );
// <table:table-row>
KoXmlElement rowElement;
rowElement = columnElement.nextSibling().toElement();
CHECK( rowElement.isNull(), false );
CHECK( rowElement.isElement(), true );
CHECK( rowElement.parentNode().isNull(), false );
CHECK( rowElement.parentNode()==sheet1Element, true );
CHECK( rowElement.firstChild().isNull(), false );
CHECK( rowElement.lastChild().isNull(), false );
CHECK( rowElement.previousSibling().isNull(), false );
CHECK( rowElement.nextSibling().isNull(), true );
CHECK( rowElement.tagName(), TQString("table-row") );
CHECK( rowElement.attributeNS(tableNS,"style-name",""), TQString("ro1") );
// <table:table-cell>
KoXmlElement cellElement;
cellElement = rowElement.firstChild().toElement();
CHECK( cellElement.isNull(), false );
CHECK( cellElement.isElement(), true );
CHECK( cellElement.parentNode().isNull(), false );
CHECK( cellElement.parentNode()==rowElement, true );
CHECK( cellElement.firstChild().isNull(), false );
CHECK( cellElement.lastChild().isNull(), false );
CHECK( cellElement.previousSibling().isNull(), true );
CHECK( cellElement.nextSibling().isNull(), true );
CHECK( cellElement.tagName(), TQString("table-cell") );
CHECK( cellElement.attributeNS(officeNS,"value-type",""), TQString("string") );
// <text:p>
KoXmlElement parElement;
parElement = cellElement.firstChild().toElement();
CHECK( parElement.isNull(), false );
CHECK( parElement.isElement(), true );
CHECK( parElement.parentNode().isNull(), false );
CHECK( parElement.parentNode()==cellElement, true );
CHECK( parElement.firstChild().isNull(), false );
CHECK( parElement.lastChild().isNull(), false );
CHECK( parElement.previousSibling().isNull(), true );
CHECK( parElement.nextSibling().isNull(), true );
CHECK( parElement.tagName(), TQString("p") );
CHECK( parElement.text(), TQString("Hello, world") );
// <table:table> for Sheet2
KoXmlElement sheet2Element;
sheet2Element = sheet1Element.nextSibling().toElement();
CHECK( sheet2Element.isNull(), false );
CHECK( sheet2Element.isElement(), true );
CHECK( sheet2Element.parentNode().isNull(), false );
CHECK( sheet2Element.parentNode()==spreadsheetElement, true );
CHECK( sheet2Element.firstChild().isNull(), false );
CHECK( sheet2Element.lastChild().isNull(), false );
CHECK( sheet2Element.previousSibling().isNull(), false );
CHECK( sheet2Element.nextSibling().isNull(), false );
CHECK( sheet2Element.tagName(), TQString("table") );
// </table:table> for Sheet3
KoXmlElement sheet3Element;
sheet3Element = sheet2Element.nextSibling().toElement();
CHECK( sheet3Element.isNull(), false );
CHECK( sheet3Element.isElement(), true );
CHECK( sheet3Element.parentNode().isNull(), false );
CHECK( sheet3Element.parentNode()==spreadsheetElement, true );
CHECK( sheet3Element.firstChild().isNull(), false );
CHECK( sheet3Element.lastChild().isNull(), false );
CHECK( sheet3Element.previousSibling().isNull(), false );
CHECK( sheet3Element.nextSibling().isNull(), true );
CHECK( sheet3Element.tagName(), TQString("table") );
}
void testSimpleOpenDocumentPresentation()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// content.xml from a simple OpenDocument presentation
// styles, declarations and unnecessary namespaces are omitted
// the first page is "Title" and has two text boxes
// the second page is
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content ";
xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
xmlstream << " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" ";
xmlstream << " xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" ";
xmlstream << " xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" ";
xmlstream << " office:version=\"1.0\">";
xmlstream << " <office:scripts/>";
xmlstream << " <office:automatic-styles/>";
xmlstream << " <office:body>";
xmlstream << " <office:presentation>";
xmlstream << " <draw:page draw:name=\"Title\" draw:style-name=\"dp1\" ";
xmlstream << " draw:master-page-name=\"lyt-cool\" ";
xmlstream << " presentation:presentation-page-layout-name=\"AL1T0\">";
xmlstream << " <draw:frame presentation:style-name=\"pr1\" ";
xmlstream << " draw:text-style-name=\"P2\" draw:layer=\"layout\" ";
xmlstream << " svg:width=\"23.912cm\" svg:height=\"3.508cm\" ";
xmlstream << " svg:x=\"2.058cm\" svg:y=\"1.543cm\" ";
xmlstream << " presentation:class=\"title\" ";
xmlstream << " presentation:user-transformed=\"true\">";
xmlstream << " <draw:text-box>";
xmlstream << " <text:p text:style-name=\"P1\">Foobar</text:p>";
xmlstream << " </draw:text-box>";
xmlstream << " </draw:frame>";
xmlstream << " <draw:frame presentation:style-name=\"pr2\" ";
xmlstream << " draw:text-style-name=\"P3\" draw:layer=\"layout\"";
xmlstream << " svg:width=\"23.912cm\" svg:height=\"13.231cm\"";
xmlstream << " svg:x=\"2.058cm\" svg:y=\"5.838cm\" ";
xmlstream << " presentation:class=\"subtitle\">";
xmlstream << " <draw:text-box>";
xmlstream << " <text:p text:style-name=\"P3\">Foo</text:p>";
xmlstream << " </draw:text-box>";
xmlstream << " </draw:frame>";
xmlstream << " <presentation:notes draw:style-name=\"dp2\">";
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\"/>";
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\">";
xmlstream << " <draw:text-box/>";
xmlstream << " </draw:frame>";
xmlstream << " </presentation:notes>";
xmlstream << " </draw:page>";
xmlstream << " <presentation:settings presentation:stay-on-top=\"true\"/>";
xmlstream << " </office:presentation>";
xmlstream << " </office:body>";
xmlstream << "</office:document-content>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
char* drawNS = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";
char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
char* presentationNS = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";
char* svgNS = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
// <office:document-content>
KoXmlElement contentElement;
contentElement = doc.documentElement();
CHECK( contentElement.isNull(), false );
CHECK( contentElement.isElement(), true );
CHECK( contentElement.parentNode().isNull(), false );
CHECK( contentElement.parentNode().toDocument()==doc, true );
CHECK( contentElement.firstChild().isNull(), false );
CHECK( contentElement.lastChild().isNull(), false );
CHECK( contentElement.previousSibling().isNull(), false );
CHECK( contentElement.nextSibling().isNull(), true );
CHECK( contentElement.localName(), TQString("document-content") );
CHECK( contentElement.hasAttributeNS(officeNS,"version"), true );
CHECK( contentElement.attributeNS(officeNS,"version",""), TQString("1.0") );
// <office:scripts>
KoXmlElement scriptsElement;
scriptsElement = KoXml::namedItemNS( contentElement, officeNS, "scripts" );
CHECK( scriptsElement.isNull(), false );
CHECK( scriptsElement.isElement(), true );
CHECK( scriptsElement.parentNode().isNull(), false );
CHECK( scriptsElement.parentNode()==contentElement, true );
CHECK( scriptsElement.firstChild().isNull(), true );
CHECK( scriptsElement.lastChild().isNull(), true );
CHECK( scriptsElement.previousSibling().isNull(), true );
CHECK( scriptsElement.nextSibling().isNull(), false );
CHECK( scriptsElement.localName(), TQString("scripts") );
// <office:automatic-styles>
KoXmlElement stylesElement;
stylesElement = KoXml::namedItemNS( contentElement, officeNS, "automatic-styles" );
CHECK( stylesElement.isNull(), false );
CHECK( stylesElement.isElement(), true );
CHECK( stylesElement.parentNode().isNull(), false );
CHECK( stylesElement.parentNode()==contentElement, true );
CHECK( stylesElement.firstChild().isNull(), true );
CHECK( stylesElement.lastChild().isNull(), true );
CHECK( stylesElement.previousSibling().isNull(), false );
CHECK( stylesElement.nextSibling().isNull(), false );
CHECK( stylesElement.localName(), TQString("automatic-styles") );
// also same <office:automatic-styles>, but without namedItemNS
KoXmlNode styles2Element;
styles2Element = scriptsElement.nextSibling().toElement();
CHECK( styles2Element.isNull(), false );
CHECK( styles2Element.isElement(), true );
CHECK( styles2Element.parentNode().isNull(), false );
CHECK( styles2Element.parentNode()==contentElement, true );
CHECK( styles2Element.firstChild().isNull(), true );
CHECK( styles2Element.lastChild().isNull(), true );
CHECK( styles2Element.previousSibling().isNull(), false );
CHECK( styles2Element.nextSibling().isNull(), false );
CHECK( styles2Element.localName(), TQString("automatic-styles") );
// <office:body>
KoXmlElement bodyElement;
bodyElement = KoXml::namedItemNS( contentElement, officeNS, "body" );
CHECK( bodyElement.isNull(), false );
CHECK( bodyElement.isElement(), true );
CHECK( bodyElement.parentNode().isNull(), false );
CHECK( bodyElement.parentNode()==contentElement, true );
CHECK( bodyElement.firstChild().isNull(), false );
CHECK( bodyElement.lastChild().isNull(), false );
CHECK( bodyElement.previousSibling().isNull(), false );
CHECK( bodyElement.nextSibling().isNull(), true );
CHECK( bodyElement.localName(), TQString("body") );
// also same <office:body>, but without namedItemNS
KoXmlElement body2Element;
body2Element = stylesElement.nextSibling().toElement();
CHECK( body2Element.isNull(), false );
CHECK( body2Element.isElement(), true );
CHECK( body2Element.parentNode().isNull(), false );
CHECK( body2Element.parentNode()==contentElement, true );
CHECK( body2Element.firstChild().isNull(), false );
CHECK( body2Element.lastChild().isNull(), false );
CHECK( body2Element.previousSibling().isNull(), false );
CHECK( body2Element.nextSibling().isNull(), true );
CHECK( body2Element.localName(), TQString("body") );
// <office:presentation>
KoXmlElement presentationElement;
presentationElement = KoXml::namedItemNS( bodyElement, officeNS, "presentation" );
CHECK( presentationElement.isNull(), false );
CHECK( presentationElement.isElement(), true );
CHECK( presentationElement.parentNode().isNull(), false );
CHECK( presentationElement.parentNode()==bodyElement, true );
CHECK( presentationElement.firstChild().isNull(), false );
CHECK( presentationElement.lastChild().isNull(), false );
CHECK( presentationElement.previousSibling().isNull(), true );
CHECK( presentationElement.nextSibling().isNull(), true );
CHECK( presentationElement.localName(), TQString("presentation") );
// the same <office:presentation>, but without namedItemNS
KoXmlElement presentation2Element;
presentation2Element = bodyElement.firstChild().toElement();
CHECK( presentation2Element.isNull(), false );
CHECK( presentation2Element.isElement(), true );
CHECK( presentation2Element.parentNode().isNull(), false );
CHECK( presentation2Element.parentNode()==bodyElement, true );
CHECK( presentation2Element.firstChild().isNull(), false );
CHECK( presentation2Element.lastChild().isNull(), false );
CHECK( presentation2Element.previousSibling().isNull(), true );
CHECK( presentation2Element.nextSibling().isNull(), true );
CHECK( presentation2Element.localName(), TQString("presentation") );
// <draw:page> for "Title"
KoXmlElement titlePageElement;
titlePageElement = presentationElement.firstChild().toElement();
CHECK( titlePageElement.isNull(), false );
CHECK( titlePageElement.isElement(), true );
CHECK( titlePageElement.parentNode().isNull(), false );
CHECK( titlePageElement.parentNode()==presentationElement, true );
CHECK( titlePageElement.firstChild().isNull(), false );
CHECK( titlePageElement.lastChild().isNull(), false );
CHECK( titlePageElement.previousSibling().isNull(), true );
CHECK( titlePageElement.nextSibling().isNull(), false );
CHECK( titlePageElement.localName(), TQString("page") );
CHECK( titlePageElement.attributeNS(drawNS,"name",""), TQString("Title") );
CHECK( titlePageElement.attributeNS(drawNS,"style-name",""), TQString("dp1") );
CHECK( titlePageElement.attributeNS(drawNS,"master-page-name",""), TQString("lyt-cool") );
CHECK( titlePageElement.attributeNS(presentationNS,
"presentation-page-layout-name",""), TQString("AL1T0") );
// <draw:frame> for the title frame
KoXmlElement titleFrameElement;
titleFrameElement = titlePageElement.firstChild().toElement();
CHECK( titleFrameElement.isNull(), false );
CHECK( titleFrameElement.isElement(), true );
CHECK( titleFrameElement.parentNode().isNull(), false );
CHECK( titleFrameElement.parentNode()==titlePageElement, true );
CHECK( titleFrameElement.firstChild().isNull(), false );
CHECK( titleFrameElement.lastChild().isNull(), false );
CHECK( titleFrameElement.previousSibling().isNull(), true );
CHECK( titleFrameElement.nextSibling().isNull(), false );
CHECK( titleFrameElement.localName(), TQString("frame") );
CHECK( titleFrameElement.attributeNS(presentationNS,"style-name",""), TQString("pr1") );
CHECK( titleFrameElement.attributeNS(presentationNS,"class",""), TQString("title") );
CHECK( titleFrameElement.attributeNS(presentationNS,"user-transformed",""), TQString("true") );
CHECK( titleFrameElement.attributeNS(drawNS,"text-style-name",""), TQString("P2") );
CHECK( titleFrameElement.attributeNS(drawNS,"layer",""), TQString("layout") );
CHECK( titleFrameElement.attributeNS(svgNS,"width",""), TQString("23.912cm") );
CHECK( titleFrameElement.attributeNS(svgNS,"height",""), TQString("3.508cm") );
CHECK( titleFrameElement.attributeNS(svgNS,"x",""), TQString("2.058cm") );
CHECK( titleFrameElement.attributeNS(svgNS,"y",""), TQString("1.543cm") );
// <draw:text-box> of the title frame
KoXmlElement titleBoxElement;
titleBoxElement = titleFrameElement.firstChild().toElement();
CHECK( titleBoxElement.isNull(), false );
CHECK( titleBoxElement.isElement(), true );
CHECK( titleBoxElement.parentNode().isNull(), false );
CHECK( titleBoxElement.parentNode()==titleFrameElement, true );
CHECK( titleBoxElement.firstChild().isNull(), false );
CHECK( titleBoxElement.lastChild().isNull(), false );
CHECK( titleBoxElement.previousSibling().isNull(), true );
CHECK( titleBoxElement.nextSibling().isNull(), true );
CHECK( titleBoxElement.localName(), TQString("text-box") );
// <text:p> for the title text-box
KoXmlElement titleParElement;
titleParElement = titleBoxElement.firstChild().toElement();
CHECK( titleParElement.isNull(), false );
CHECK( titleParElement.isElement(), true );
CHECK( titleParElement.parentNode().isNull(), false );
CHECK( titleParElement.parentNode()==titleBoxElement, true );
CHECK( titleParElement.firstChild().isNull(), false );
CHECK( titleParElement.lastChild().isNull(), false );
CHECK( titleParElement.previousSibling().isNull(), true );
CHECK( titleParElement.nextSibling().isNull(), true );
CHECK( titleParElement.localName(), TQString("p") );
CHECK( titleParElement.attributeNS(textNS,"style-name",""), TQString("P1") );
CHECK( titleParElement.text(), TQString("Foobar") );
// <draw:frame> for the subtitle frame
KoXmlElement subtitleFrameElement;
subtitleFrameElement = titleFrameElement.nextSibling().toElement();
CHECK( subtitleFrameElement.isNull(), false );
CHECK( subtitleFrameElement.isElement(), true );
CHECK( subtitleFrameElement.parentNode().isNull(), false );
CHECK( subtitleFrameElement.parentNode()==titlePageElement, true );
CHECK( subtitleFrameElement.firstChild().isNull(), false );
CHECK( subtitleFrameElement.lastChild().isNull(), false );
CHECK( subtitleFrameElement.previousSibling().isNull(), false );
CHECK( subtitleFrameElement.nextSibling().isNull(), false );
CHECK( subtitleFrameElement.localName(), TQString("frame") );
CHECK( subtitleFrameElement.attributeNS(presentationNS,"style-name",""), TQString("pr2") );
CHECK( subtitleFrameElement.attributeNS(presentationNS,"class",""), TQString("subtitle") );
CHECK( subtitleFrameElement.hasAttributeNS(presentationNS,"user-transformed"), false );
CHECK( subtitleFrameElement.attributeNS(drawNS,"text-style-name",""), TQString("P3") );
CHECK( subtitleFrameElement.attributeNS(drawNS,"layer",""), TQString("layout") );
CHECK( subtitleFrameElement.attributeNS(svgNS,"width",""), TQString("23.912cm") );
CHECK( subtitleFrameElement.attributeNS(svgNS,"height",""), TQString("13.231cm") );
CHECK( subtitleFrameElement.attributeNS(svgNS,"x",""), TQString("2.058cm") );
CHECK( subtitleFrameElement.attributeNS(svgNS,"y",""), TQString("5.838cm") );
// <draw:text-box> of the subtitle frame
KoXmlElement subtitleBoxElement;
subtitleBoxElement = subtitleFrameElement.firstChild().toElement();
CHECK( subtitleBoxElement.isNull(), false );
CHECK( subtitleBoxElement.isElement(), true );
CHECK( subtitleBoxElement.parentNode().isNull(), false );
CHECK( subtitleBoxElement.parentNode()==subtitleFrameElement, true );
CHECK( subtitleBoxElement.firstChild().isNull(), false );
CHECK( subtitleBoxElement.lastChild().isNull(), false );
CHECK( subtitleBoxElement.previousSibling().isNull(), true );
CHECK( subtitleBoxElement.nextSibling().isNull(), true );
CHECK( subtitleBoxElement.localName(), TQString("text-box") );
// <text:p> for the subtitle text-box
KoXmlElement subtitleParElement;
subtitleParElement = subtitleBoxElement.firstChild().toElement();
CHECK( subtitleParElement.isNull(), false );
CHECK( subtitleParElement.isElement(), true );
CHECK( subtitleParElement.parentNode().isNull(), false );
CHECK( subtitleParElement.parentNode()==subtitleBoxElement, true );
CHECK( subtitleParElement.firstChild().isNull(), false );
CHECK( subtitleParElement.lastChild().isNull(), false );
CHECK( subtitleParElement.previousSibling().isNull(), true );
CHECK( subtitleParElement.nextSibling().isNull(), true );
CHECK( subtitleParElement.localName(), TQString("p") );
CHECK( subtitleParElement.attributeNS(textNS,"style-name",""), TQString("P3") );
CHECK( subtitleParElement.text(), TQString("Foo") );
}
void testSimpleOpenDocumentFormula()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// content.xml from a simple OpenDocument formula
// this is essentially MathML
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<!DOCTYPE math:math PUBLIC \"-//OpenOffice.org//DTD Modified W3C MathML 1.01//EN\" \"math.dtd\">";
xmlstream << "<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">";
xmlstream << " <math:semantics>";
xmlstream << " <math:mrow>";
xmlstream << " <math:mi>E</math:mi>";
xmlstream << " <math:mo math:stretchy=\"false\">=</math:mo>";
xmlstream << " <math:msup>";
xmlstream << " <math:mi math:fontstyle=\"italic\">mc</math:mi>";
xmlstream << " <math:mn>2</math:mn>";
xmlstream << " </math:msup>";
xmlstream << " </math:mrow>";
xmlstream << " <math:annotation math:encoding=\"StarMath 5.0\">E = mc^2 </math:annotation>";
xmlstream << " </math:semantics>";
xmlstream << "</math:math>";
KoXmlDocument doc;
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
char* mathNS = "http://www.w3.org/1998/Math/MathML";
// <math:math>
KoXmlElement mathElement;
mathElement = doc.documentElement();
CHECK( mathElement.isNull(), false );
CHECK( mathElement.isElement(), true );
CHECK( mathElement.parentNode().isNull(), false );
CHECK( mathElement.parentNode().toDocument()==doc, true );
CHECK( mathElement.firstChild().isNull(), false );
CHECK( mathElement.lastChild().isNull(), false );
CHECK( mathElement.previousSibling().isNull(), false );
CHECK( mathElement.nextSibling().isNull(), true );
CHECK( mathElement.localName(), TQString("math") );
// <math:semantics>
KoXmlElement semanticsElement;
semanticsElement = KoXml::namedItemNS( mathElement, mathNS, "semantics" );
CHECK( semanticsElement.isNull(), false );
CHECK( semanticsElement.isElement(), true );
CHECK( semanticsElement.parentNode().isNull(), false );
CHECK( semanticsElement.parentNode().toElement()==mathElement, true );
CHECK( semanticsElement.firstChild().isNull(), false );
CHECK( semanticsElement.lastChild().isNull(), false );
CHECK( semanticsElement.previousSibling().isNull(), true );
CHECK( semanticsElement.nextSibling().isNull(), true );
CHECK( semanticsElement.localName(), TQString("semantics") );
// the same <math:semantics> but without namedItemNS
KoXmlElement semantics2Element;
semantics2Element = mathElement.firstChild().toElement();
CHECK( semantics2Element.isNull(), false );
CHECK( semantics2Element.isElement(), true );
CHECK( semantics2Element.parentNode().isNull(), false );
CHECK( semantics2Element.parentNode().toElement()==mathElement, true );
CHECK( semantics2Element.firstChild().isNull(), false );
CHECK( semantics2Element.lastChild().isNull(), false );
CHECK( semantics2Element.previousSibling().isNull(), true );
CHECK( semantics2Element.nextSibling().isNull(), true );
CHECK( semantics2Element.localName(), TQString("semantics") );
// <math:mrow>
KoXmlElement mrowElement;
mrowElement = semanticsElement.firstChild().toElement();
CHECK( mrowElement.isNull(), false );
CHECK( mrowElement.isElement(), true );
CHECK( mrowElement.parentNode().isNull(), false );
CHECK( mrowElement.parentNode().toElement()==semanticsElement, true );
CHECK( mrowElement.firstChild().isNull(), false );
CHECK( mrowElement.lastChild().isNull(), false );
CHECK( mrowElement.previousSibling().isNull(), true );
CHECK( mrowElement.nextSibling().isNull(), false );
CHECK( mrowElement.localName(), TQString("mrow") );
// <math:mi> for "E"
KoXmlElement miElement;
miElement = mrowElement.firstChild().toElement();
CHECK( miElement.isNull(), false );
CHECK( miElement.isElement(), true );
CHECK( miElement.parentNode().isNull(), false );
CHECK( miElement.parentNode().toElement()==mrowElement, true );
CHECK( miElement.firstChild().isNull(), false );
CHECK( miElement.lastChild().isNull(), false );
CHECK( miElement.previousSibling().isNull(), true );
CHECK( miElement.nextSibling().isNull(), false );
CHECK( miElement.localName(), TQString("mi") );
// <math:mo> for "="
KoXmlElement moElement;
moElement = miElement.nextSibling().toElement();
CHECK( moElement.isNull(), false );
CHECK( moElement.isElement(), true );
CHECK( moElement.parentNode().isNull(), false );
CHECK( moElement.parentNode().toElement()==mrowElement, true );
CHECK( moElement.firstChild().isNull(), false );
CHECK( moElement.lastChild().isNull(), false );
CHECK( moElement.previousSibling().isNull(), false );
CHECK( moElement.nextSibling().isNull(), false );
CHECK( moElement.localName(), TQString("mo") );
CHECK( moElement.attributeNS(mathNS,"stretchy",""), TQString("false") );
// <math:msup> for "mc" and superscripted "2"
KoXmlElement msupElement;
msupElement = moElement.nextSibling().toElement();
CHECK( msupElement.isNull(), false );
CHECK( msupElement.isElement(), true );
CHECK( msupElement.parentNode().isNull(), false );
CHECK( msupElement.parentNode().toElement()==mrowElement, true );
CHECK( msupElement.firstChild().isNull(), false );
CHECK( msupElement.lastChild().isNull(), false );
CHECK( msupElement.previousSibling().isNull(), false );
CHECK( msupElement.nextSibling().isNull(), true );
CHECK( msupElement.localName(), TQString("msup") );
// <math:mi> inside the <math:msup> for "mc"
KoXmlElement mcElement;
mcElement = msupElement.firstChild().toElement();
CHECK( mcElement.isNull(), false );
CHECK( mcElement.isElement(), true );
CHECK( mcElement.parentNode().isNull(), false );
CHECK( mcElement.parentNode().toElement()==msupElement, true );
CHECK( mcElement.firstChild().isNull(), false );
CHECK( mcElement.lastChild().isNull(), false );
CHECK( mcElement.previousSibling().isNull(), true );
CHECK( mcElement.nextSibling().isNull(), false );
CHECK( mcElement.localName(), TQString("mi") );
CHECK( mcElement.text(), TQString("mc") );
CHECK( mcElement.attributeNS(mathNS,"fontstyle",""), TQString("italic") );
// <math:mn> inside the <math:msup> for "2" (superscript)
KoXmlElement mnElement;
mnElement = mcElement.nextSibling().toElement();
CHECK( mnElement.isNull(), false );
CHECK( mnElement.isElement(), true );
CHECK( mnElement.parentNode().isNull(), false );
CHECK( mnElement.parentNode().toElement()==msupElement, true );
CHECK( mnElement.firstChild().isNull(), false );
CHECK( mnElement.lastChild().isNull(), false );
CHECK( mnElement.previousSibling().isNull(), false );
CHECK( mnElement.nextSibling().isNull(), true );
CHECK( mnElement.localName(), TQString("mn") );
CHECK( mnElement.text(), TQString("2") );
// <math:annotation>
KoXmlElement annotationElement;
annotationElement = semanticsElement.lastChild().toElement();
CHECK( annotationElement.isNull(), false );
CHECK( annotationElement.isElement(), true );
CHECK( annotationElement.parentNode().isNull(), false );
CHECK( annotationElement.parentNode().toElement()==semanticsElement, true );
CHECK( annotationElement.firstChild().isNull(), false );
CHECK( annotationElement.lastChild().isNull(), false );
CHECK( annotationElement.previousSibling().isNull(), false );
CHECK( annotationElement.nextSibling().isNull(), true );
CHECK( annotationElement.localName(), TQString("annotation") );
CHECK( annotationElement.text(), TQString("E = mc^2 ") );
CHECK( annotationElement.attributeNS(mathNS,"encoding",""), TQString("StarMath 5.0") );
}
void testLargeOpenDocumentSpreadsheet()
{
TQString errorMsg;
int errorLine = 0;
int errorColumn = 0;
int sheetCount = 4;
int rowCount = 200;
int colCount = 200*2;
TQByteArray xmlbuf;
TQBuffer xmldevice( xmlbuf );
TQTextStream xmlstream( xmlbuf, IO_WriteOnly );
// content.xml
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content ";
xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" >";
xmlstream << "<office:body>";
xmlstream << "<office:spreadsheet>";
for( int i = 0; i < sheetCount; i++ )
{
TQString sheetName = TQString("Sheet%1").arg(i+1);
xmlstream << "<table:table table:name=\"" << sheetName;
xmlstream << "\" table:print=\"false\">";
for( int j = 0; j < rowCount; j++ )
{
xmlstream << "<table:table-row>";
for( int k = 0; k < colCount; k++ )
{
xmlstream << "<table:table-cell office:value-type=\"string\">";
xmlstream << "<text:p>Hello, world</text:p>";
xmlstream << "</table:table-cell>";
}
xmlstream << "</table:table-row>";
}
xmlstream << "</table:table>";
}
xmlstream << "</office:spreadsheet>";
xmlstream << "</office:body>";
xmlstream << "</office:document-content>";
printf("Raw XML size: %d KB\n", xmlbuf.size()/1024 );
TQTime timer;
timer.start();
#if 1
// just to test parsing speed with plain dumb handler
TQXmlSimpleReader* reader = new TQXmlSimpleReader;
reader->setFeature( "http://xml.org/sax/features/namespaces", true );
TQXmlDefaultHandler handler;
reader->setContentHandler( &handler );
reader->setErrorHandler( &handler );
reader->setLexicalHandler( &handler );
reader->setDeclHandler( &handler );
reader->setDTDHandler( &handler );
TQXmlInputSource xmlSource;
xmlSource.setData( TQString::fromUtf8( xmlbuf.data(), xmlbuf.size() ) );
timer.start();
reader->parse( &xmlSource );
printf("Large spreadsheet: TQXmlDefaultHandler parsing time is %d ms\n", timer.elapsed() );
delete reader;
#endif
timer.start();
KoXmlDocument doc;
// uncomment to see the performance if on-demand/lazy loading is not used
// will definitely eat more memory
#ifndef KOXML_USE_TQDOM
doc.setFastLoading( true );
#endif
CHECK( doc.setContent( &xmldevice, true, &errorMsg, &errorLine, &errorColumn ), true );
CHECK( errorMsg.isEmpty(), true );
CHECK( errorLine, 0 );
CHECK( errorColumn, 0 );
printf("Large spreadsheet: parsing time is %d ms\n", timer.elapsed() );
// release memory taken by the XML document content
xmlbuf.resize( 0 );
// namespaces that will be used
TQString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
TQString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
TQString textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
// <office:document-content>
KoXmlElement contentElement;
contentElement = doc.documentElement();
CHECK( contentElement.isNull(), false );
CHECK( contentElement.isElement(), true );
CHECK( contentElement.localName(), TQString("document-content") );
// <office:body>
KoXmlElement bodyElement;
bodyElement = contentElement.firstChild().toElement();
CHECK( bodyElement.isNull(), false );
CHECK( bodyElement.isElement(), true );
CHECK( bodyElement.localName(), TQString("body") );
// <office:spreadsheet>
KoXmlElement spreadsheetElement;
spreadsheetElement = bodyElement.firstChild().toElement();
CHECK( spreadsheetElement.isNull(), false );
CHECK( spreadsheetElement.isElement(), true );
CHECK( spreadsheetElement.localName(), TQString("spreadsheet") );
// now we visit every sheet, every row, every cell
timer.start();
KoXmlElement tableElement;
tableElement = spreadsheetElement.firstChild().toElement();
for( int table=0; table < sheetCount; table++ )
{
TQString tableName = TQString("Sheet%1").arg(table+1);
CHECK( tableElement.isNull(), false );
CHECK( tableElement.isElement(), true );
CHECK( tableElement.localName(), TQString("table") );
CHECK( tableElement.hasAttributeNS(tableNS,"name"), true );
CHECK( tableElement.attributeNS(tableNS,"name",""), tableName );
CHECK( tableElement.attributeNS(tableNS,"print",""), TQString("false") );
// load everything for this table
KoXml::load( tableElement, 99 );
CHECK( tableElement.parentNode().isNull(), false );
CHECK( tableElement.parentNode()==spreadsheetElement, true );
CHECK( tableElement.firstChild().isNull(), false );
CHECK( tableElement.lastChild().isNull(), false );
KoXmlElement rowElement;
rowElement = tableElement.firstChild().toElement();
for( int row=0; row < rowCount; row++ )
{
CHECK( rowElement.isNull(), false );
CHECK( rowElement.isElement(), true );
CHECK( rowElement.localName(), TQString("table-row") );
CHECK( rowElement.parentNode().isNull(), false );
CHECK( rowElement.parentNode()==tableElement, true );
CHECK( rowElement.firstChild().isNull(), false );
CHECK( rowElement.lastChild().isNull(), false );
KoXmlElement cellElement;
cellElement = rowElement.firstChild().toElement();
for( int col=0; col < colCount; col++ )
{
CHECK( cellElement.isNull(), false );
CHECK( cellElement.isElement(), true );
CHECK( cellElement.localName(), TQString("table-cell") );
CHECK( cellElement.text(), TQString("Hello, world") );
CHECK( cellElement.hasAttributeNS(officeNS,"value-type"), true );
CHECK( cellElement.attributeNS(officeNS,"value-type",""), TQString("string" ) );
CHECK( cellElement.parentNode().isNull(), false );
CHECK( cellElement.parentNode()==rowElement, true );
CHECK( cellElement.firstChild().isNull(), false );
CHECK( cellElement.lastChild().isNull(), false );
cellElement = cellElement.nextSibling().toElement();
}
//KoXml::unload( rowElement );
rowElement = rowElement.nextSibling().toElement();
}
KoXml::unload( tableElement );
tableElement = tableElement.nextSibling().toElement();
}
printf("Large spreadsheet: iterating time is %d ms\n", timer.elapsed() );
}
int main( int argc, char** argv )
{
Q_UNUSED( argc );
Q_UNUSED( argv );
testNode();
testElement();
testAttributes();
testText();
testCDATA();
testDocument();
testNamespace();
testUnload();
testSimpleXML();
testRootError();
testMismatchedTag();
testSimpleOpenDocumentText();
testSimpleOpenDocumentSpreadsheet();
testSimpleOpenDocumentPresentation();
testSimpleOpenDocumentFormula();
// testLargeOpenDocumentSpreadsheet();
#ifdef KOXML_USE_TQDOM
printf("Using TQDom: ");
#else
printf("Using KoXml: ");
#endif
printf("%d tests, %d failed\n", testCount, testFailed );
return testFailed;
}