1 #include <QTest>
2
3 #include <QBuffer>
4 #include <QFile>
5 #include <QDateTime>
6 #include <QProcess>
7 #include <QString>
8 #include <QTextStream>
9
10 #include <KoXmlReader.h>
11
12
13 class TestXmlReaderWithoutSpaces : public QObject
14 {
15 Q_OBJECT
16 private Q_SLOTS:
17 void initTestCase();
18 void testNode();
19 void testElement();
20 void testAttributes();
21 void testText();
22 void testCDATA();
23 void testDocument();
24 void testDocumentType();
25 void testNamespace();
26 void testParseQString();
27 void testUnload();
28 void testSimpleXML();
29 void testRootError();
30 void testMismatchedTag();
31 void testConvertQDomDocument();
32 void testConvertQDomElement();
33 void testSimpleOpenDocumentText();
34 void testWhitespace();
35 void testSimpleOpenDocumentSpreadsheet();
36 void testSimpleOpenDocumentPresentation();
37 void testSimpleOpenDocumentFormula();
38 void testLargeOpenDocumentSpreadsheet();
39 void testExternalOpenDocumentSpreadsheet(const QString& filename);
40 };
41
initTestCase()42 void TestXmlReaderWithoutSpaces::initTestCase()
43 {
44 QLoggingCategory::setFilterRules("*.debug=false\n"
45 "calligra.lib.odf=true\ncalligra.lib.store=true");
46 }
47
testNode()48 void TestXmlReaderWithoutSpaces::testNode()
49 {
50 QString errorMsg;
51 int errorLine = 0;
52 int errorColumn = 0;
53
54 QBuffer xmldevice;
55 xmldevice.open(QIODevice::WriteOnly);
56 QTextStream xmlstream(&xmldevice);
57 xmlstream << "<earth>";
58 xmlstream << "<continents>";
59 xmlstream << "<asia/>";
60 xmlstream << "<africa/>";
61 xmlstream << "<europe/>";
62 xmlstream << "<america/>";
63 xmlstream << "<australia/>";
64 xmlstream << "<antartic/>";
65 xmlstream << "</continents>";
66 xmlstream << "<oceans>";
67 xmlstream << "<pacific/>";
68 xmlstream << "<atlantic/>";
69 xmlstream << "</oceans>";
70 xmlstream << "</earth>";
71 xmldevice.close();
72
73 KoXmlDocument doc(false);
74 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
75 QCOMPARE(errorMsg.isEmpty(), true);
76 QCOMPARE(errorLine, 0);
77 QCOMPARE(errorColumn, 0);
78
79 // null node
80 KoXmlNode node1;
81 QCOMPARE(node1.nodeName(), QString());
82 QCOMPARE(node1.isNull(), true);
83 QCOMPARE(node1.isElement(), false);
84 QCOMPARE(node1.isDocument(), false);
85 QCOMPARE(node1.ownerDocument().isNull(), true);
86 QCOMPARE(node1.parentNode().isNull(), true);
87 QCOMPARE(node1.hasChildNodes(), false);
88 QCOMPARE(KoXml::childNodesCount(node1), 0);
89 QCOMPARE(node1.firstChild().isNull(), true);
90 QCOMPARE(node1.lastChild().isNull(), true);
91 QCOMPARE(node1.previousSibling().isNull(), true);
92 QCOMPARE(node1.nextSibling().isNull(), true);
93
94 // compare with another null node
95 KoXmlNode node2;
96 QCOMPARE(node2.isNull(), true);
97 QCOMPARE(node1 == node2, true);
98 QCOMPARE(node1 != node2, false);
99
100 // a node which is a document
101 KoXmlNode node3 = doc;
102 QCOMPARE(node3.nodeName(), QString("#document"));
103 QCOMPARE(node3.isNull(), false);
104 QCOMPARE(node3.isElement(), false);
105 QCOMPARE(node3.isText(), false);
106 QCOMPARE(node3.isDocument(), true);
107 QCOMPARE(node3.ownerDocument().isNull(), false);
108 QCOMPARE(node3.ownerDocument() == doc, true);
109 QCOMPARE(node3.toDocument() == doc, true);
110 QCOMPARE(KoXml::childNodesCount(node3), 1);
111
112 // convert to document and the compare
113 KoXmlDocument doc2 = node3.toDocument();
114 QCOMPARE(doc2.nodeName(), QString("#document"));
115 QCOMPARE(doc2.isNull(), false);
116 QCOMPARE(doc2.isDocument(), true);
117 QCOMPARE(node3 == doc2, true);
118 QCOMPARE(KoXml::childNodesCount(doc2), 1);
119
120 // a document is of course can't be converted to element
121 KoXmlElement invalidElement = node3.toElement();
122 QCOMPARE(invalidElement.nodeName(), QString());
123 QCOMPARE(invalidElement.isNull(), true);
124 QCOMPARE(invalidElement.isElement(), false);
125 QCOMPARE(invalidElement.isText(), false);
126 QCOMPARE(invalidElement.isDocument(), false);
127
128 // clear() makes it a null node again
129 node3.clear();
130 QCOMPARE(node3.isNull(), true);
131 QCOMPARE(node3.nodeName(), QString());
132 QCOMPARE(node3.isElement(), false);
133 QCOMPARE(node3.isText(), false);
134 QCOMPARE(node3.isDocument(), false);
135 QCOMPARE(node3.ownerDocument().isNull(), true);
136 QCOMPARE(node1 == node3, true);
137 QCOMPARE(node1 != node3, false);
138
139 // a node which is an element for <earth>
140 KoXmlNode node4 = doc.firstChild();
141 QCOMPARE(node4.isNull(), false);
142 QCOMPARE(node4.isElement(), true);
143 QCOMPARE(node4.isText(), false);
144 QCOMPARE(node4.isDocument(), false);
145 QCOMPARE(node4.hasChildNodes(), true);
146 QCOMPARE(KoXml::childNodesCount(node4), 2);
147 QCOMPARE(node4.ownerDocument() == doc, true);
148 QCOMPARE(node4.toElement() == doc.firstChild().toElement(), true);
149
150 // clear() makes it a null node again
151 node4.clear();
152 QCOMPARE(node4.isNull(), true);
153 QCOMPARE(node4.isElement(), false);
154 QCOMPARE(node4.isText(), false);
155 QCOMPARE(node4.isDocument(), false);
156 QCOMPARE(node4 == node1, true);
157 QCOMPARE(node4 != node1, false);
158 QCOMPARE(KoXml::childNodesCount(node4), 0);
159
160 // a node which is an element for <continents>
161 KoXmlNode node5 = doc.firstChild().firstChild();
162 QCOMPARE(node5.nodeName(), QString("continents"));
163 QCOMPARE(node5.isNull(), false);
164 QCOMPARE(node5.isElement(), true);
165 QCOMPARE(node5.isText(), false);
166 QCOMPARE(node5.isDocument(), false);
167 QCOMPARE(node5.hasChildNodes(), true);
168 QCOMPARE(KoXml::childNodesCount(node5), 6);
169 QCOMPARE(node5.ownerDocument() == doc, true);
170
171 // convert to element and the compare
172 KoXmlElement continentsElement = node5.toElement();
173 QCOMPARE(node5 == continentsElement, true);
174 QCOMPARE(continentsElement.isNull(), false);
175 QCOMPARE(continentsElement.isElement(), true);
176 QCOMPARE(continentsElement.isText(), false);
177 QCOMPARE(continentsElement.hasChildNodes(), true);
178 QCOMPARE(KoXml::childNodesCount(continentsElement), 6);
179 QCOMPARE(continentsElement.ownerDocument() == doc, true);
180
181 // and it doesn't make sense to convert that node to document
182 KoXmlDocument invalidDoc = node5.toDocument();
183 QCOMPARE(invalidDoc.isNull(), true);
184 QCOMPARE(invalidDoc.isElement(), false);
185 QCOMPARE(invalidDoc.isText(), false);
186 QCOMPARE(invalidDoc.isDocument(), false);
187
188 // node for <europe> using namedItem() function
189 KoXmlNode europeNode = continentsElement.namedItem(QString("europe"));
190 QCOMPARE(europeNode.nodeName(), QString("europe"));
191 QCOMPARE(europeNode.isNull(), false);
192 QCOMPARE(europeNode.isElement(), true);
193 QCOMPARE(europeNode.isText(), false);
194 QCOMPARE(europeNode.hasChildNodes(), false);
195 QCOMPARE(KoXml::childNodesCount(europeNode), 0);
196 QCOMPARE(europeNode.ownerDocument() == doc, true);
197
198 // search non-existing node
199 KoXmlNode fooNode = continentsElement.namedItem(QString("foobar"));
200 QCOMPARE(fooNode.isNull(), true);
201 QCOMPARE(fooNode.isElement(), false);
202 QCOMPARE(fooNode.isText(), false);
203 QCOMPARE(fooNode.isCDATASection(), false);
204 QCOMPARE(KoXml::childNodesCount(fooNode), 0);
205 }
206
testElement()207 void TestXmlReaderWithoutSpaces::testElement()
208 {
209 QString errorMsg;
210 int errorLine = 0;
211 int errorColumn = 0;
212
213 QBuffer xmldevice;
214 xmldevice.open(QIODevice::WriteOnly);
215 QTextStream xmlstream(&xmldevice);
216 xmlstream << "<html>";
217 xmlstream << "<body bgcolor=\"#000\">";
218 xmlstream << "<p>";
219 xmlstream << "Hello, world!";
220 xmlstream << "</p>";
221 xmlstream << "</body>";
222 xmlstream << "</html>";
223 xmldevice.close();
224
225 KoXmlDocument doc(false);
226 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
227 QCOMPARE(errorMsg.isEmpty(), true);
228 QCOMPARE(errorLine, 0);
229 QCOMPARE(errorColumn, 0);
230
231 // element for <html>
232 KoXmlElement rootElement;
233 rootElement = doc.documentElement();
234 QCOMPARE(rootElement.nodeName(), QString("html"));
235 QCOMPARE(rootElement.isNull(), false);
236 QCOMPARE(rootElement.isElement(), true);
237 QCOMPARE(rootElement.isDocument(), false);
238 QCOMPARE(rootElement.ownerDocument().isNull(), false);
239 QCOMPARE(rootElement.ownerDocument() == doc, true);
240 QCOMPARE(rootElement.parentNode().isNull(), false);
241 QCOMPARE(rootElement.parentNode().toDocument() == doc, true);
242 QCOMPARE(rootElement.hasChildNodes(), true);
243 QCOMPARE(KoXml::childNodesCount(rootElement), 1);
244 QCOMPARE(rootElement.tagName(), QString("html"));
245 QCOMPARE(rootElement.prefix().isNull(), true);
246
247 // element for <body>
248 KoXmlElement bodyElement;
249 bodyElement = rootElement.firstChild().toElement();
250 QCOMPARE(bodyElement.nodeName(), QString("body"));
251 QCOMPARE(bodyElement.isNull(), false);
252 QCOMPARE(bodyElement.isElement(), true);
253 QCOMPARE(bodyElement.isDocument(), false);
254 QCOMPARE(bodyElement.ownerDocument().isNull(), false);
255 QCOMPARE(bodyElement.ownerDocument() == doc, true);
256 QCOMPARE(bodyElement.parentNode().isNull(), false);
257 QCOMPARE(bodyElement.parentNode() == rootElement, true);
258 QCOMPARE(bodyElement.hasChildNodes(), true);
259 QCOMPARE(KoXml::childNodesCount(bodyElement), 1);
260 QCOMPARE(bodyElement.tagName(), QString("body"));
261 QCOMPARE(bodyElement.prefix().isNull(), true);
262 QCOMPARE(bodyElement.hasAttribute("bgcolor"), true);
263 QCOMPARE(bodyElement.attribute("bgcolor"), QString("#000"));
264
265 // a shared copy of <body>, will still have access to attribute bgcolor
266 KoXmlElement body2Element;
267 body2Element = bodyElement;
268 QCOMPARE(body2Element.nodeName(), QString("body"));
269 QCOMPARE(body2Element.isNull(), false);
270 QCOMPARE(body2Element.isElement(), true);
271 QCOMPARE(body2Element.isDocument(), false);
272 QCOMPARE(body2Element.ownerDocument().isNull(), false);
273 QCOMPARE(body2Element.ownerDocument() == doc, true);
274 QCOMPARE(body2Element == bodyElement, true);
275 QCOMPARE(body2Element != bodyElement, false);
276 QCOMPARE(body2Element.hasChildNodes(), true);
277 QCOMPARE(KoXml::childNodesCount(body2Element), 1);
278 QCOMPARE(body2Element.tagName(), QString("body"));
279 QCOMPARE(body2Element.prefix().isNull(), true);
280 QCOMPARE(body2Element.hasAttribute("bgcolor"), true);
281 QCOMPARE(body2Element.attribute("bgcolor"), QString("#000"));
282
283 // empty element, by default constructor
284 KoXmlElement testElement;
285 QCOMPARE(testElement.nodeName(), QString());
286 QCOMPARE(testElement.isNull(), true);
287 QCOMPARE(testElement.isElement(), false);
288 QCOMPARE(testElement.isDocument(), false);
289 QCOMPARE(testElement.ownerDocument().isNull(), true);
290 QCOMPARE(testElement.ownerDocument() != doc, true);
291 QCOMPARE(testElement == rootElement, false);
292 QCOMPARE(testElement != rootElement, true);
293 QCOMPARE(testElement.parentNode().isNull(), true);
294 QCOMPARE(testElement.hasChildNodes(), false);
295 QCOMPARE(KoXml::childNodesCount(testElement), 0);
296
297 // check assignment operator
298 testElement = rootElement;
299 QCOMPARE(testElement.nodeName(), QString("html"));
300 QCOMPARE(testElement.isNull(), false);
301 QCOMPARE(testElement.isElement(), true);
302 QCOMPARE(testElement.isDocument(), false);
303 QCOMPARE(testElement == rootElement, true);
304 QCOMPARE(testElement != rootElement, false);
305 QCOMPARE(testElement.parentNode().isNull(), false);
306 QCOMPARE(testElement.parentNode().toDocument() == doc, true);
307 QCOMPARE(testElement.tagName(), QString("html"));
308 QCOMPARE(testElement.prefix().isNull(), true);
309 QCOMPARE(KoXml::childNodesCount(testElement), 1);
310
311 // assigned from another empty element
312 testElement = KoXmlElement();
313 QCOMPARE(testElement.isNull(), true);
314 QCOMPARE(testElement != rootElement, true);
315
316 // assigned from <body>
317 testElement = bodyElement;
318 QCOMPARE(testElement.isNull(), false);
319 QCOMPARE(testElement.isElement(), true);
320 QCOMPARE(testElement.isDocument(), false);
321 QCOMPARE(testElement.ownerDocument().isNull(), false);
322 QCOMPARE(testElement.ownerDocument() == doc, true);
323 QCOMPARE(testElement == bodyElement, true);
324 QCOMPARE(testElement.parentNode().isNull(), false);
325 QCOMPARE(testElement.tagName(), QString("body"));
326 QCOMPARE(testElement.prefix().isNull(), true);
327 QCOMPARE(testElement.hasChildNodes(), true);
328 QCOMPARE(KoXml::childNodesCount(testElement), 1);
329
330 // copy constructor
331 KoXmlElement dummyElement(rootElement);
332 QCOMPARE(dummyElement.isNull(), false);
333 QCOMPARE(dummyElement.isElement(), true);
334 QCOMPARE(dummyElement.isDocument(), false);
335 QCOMPARE(dummyElement.ownerDocument().isNull(), false);
336 QCOMPARE(dummyElement.ownerDocument() == doc, true);
337 QCOMPARE(dummyElement == rootElement, true);
338 QCOMPARE(dummyElement.parentNode().isNull(), false);
339 QCOMPARE(dummyElement.hasChildNodes(), true);
340 QCOMPARE(KoXml::childNodesCount(dummyElement), 1);
341 QCOMPARE(dummyElement.tagName(), QString("html"));
342 QCOMPARE(dummyElement.prefix().isNull(), true);
343
344 // clear() turns element to null node
345 dummyElement.clear();
346 QCOMPARE(dummyElement.isNull(), true);
347 QCOMPARE(dummyElement.isElement(), false);
348 QCOMPARE(dummyElement.isDocument(), false);
349 QCOMPARE(dummyElement.ownerDocument().isNull(), true);
350 QCOMPARE(dummyElement.ownerDocument() == doc, false);
351 QCOMPARE(dummyElement.hasChildNodes(), false);
352 QCOMPARE(KoXml::childNodesCount(dummyElement), 0);
353 QCOMPARE(dummyElement == rootElement, false);
354 QCOMPARE(dummyElement != rootElement, true);
355
356 // check for plain null node converted to element
357 KoXmlNode dummyNode;
358 dummyElement = dummyNode.toElement();
359 QCOMPARE(dummyElement.isNull(), true);
360 QCOMPARE(dummyElement.isElement(), false);
361 QCOMPARE(dummyElement.isDocument(), false);
362 QCOMPARE(dummyElement.ownerDocument().isNull(), true);
363 QCOMPARE(dummyElement.hasChildNodes(), false);
364 QCOMPARE(KoXml::childNodesCount(dummyElement), 0);
365 QCOMPARE(dummyElement.ownerDocument() == doc, false);
366 }
367
testAttributes()368 void TestXmlReaderWithoutSpaces::testAttributes()
369 {
370 QString errorMsg;
371 int errorLine = 0;
372 int errorColumn = 0;
373
374 QBuffer xmldevice;
375 xmldevice.open(QIODevice::WriteOnly);
376 QTextStream xmlstream(&xmldevice);
377 xmlstream << "<p>";
378 xmlstream << "<img src=\"foo.png\" width=\"300\" height=\"150\"/>";
379 xmlstream << "</p>";
380 xmldevice.close();
381
382 KoXmlDocument doc(false);
383 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
384 QCOMPARE(errorMsg.isEmpty(), true);
385 QCOMPARE(errorLine, 0);
386 QCOMPARE(errorColumn, 0);
387
388 KoXmlElement rootElement;
389 rootElement = doc.documentElement();
390 QCOMPARE(rootElement.isNull(), false);
391 QCOMPARE(rootElement.isElement(), true);
392 QCOMPARE(rootElement.parentNode().isNull(), false);
393 QCOMPARE(rootElement.parentNode().toDocument() == doc, true);
394 QCOMPARE(rootElement.tagName(), QString("p"));
395 QCOMPARE(rootElement.prefix().isNull(), true);
396 QCOMPARE(KoXml::childNodesCount(rootElement), 1);
397
398 KoXmlElement imgElement;
399 imgElement = rootElement.firstChild().toElement();
400 QCOMPARE(imgElement.isNull(), false);
401 QCOMPARE(imgElement.isElement(), true);
402 QCOMPARE(imgElement.tagName(), QString("img"));
403 QCOMPARE(imgElement.prefix().isNull(), true);
404 QCOMPARE(KoXml::childNodesCount(imgElement), 0);
405 QCOMPARE(imgElement.hasAttribute("src"), true);
406 QCOMPARE(imgElement.hasAttribute("width"), true);
407 QCOMPARE(imgElement.hasAttribute("height"), true);
408 QCOMPARE(imgElement.hasAttribute("non-exist"), false);
409 QCOMPARE(imgElement.hasAttribute("SRC"), false);
410 QCOMPARE(imgElement.attribute("src"), QString("foo.png"));
411 QCOMPARE(imgElement.attribute("width"), QString("300"));
412 QCOMPARE(imgElement.attribute("width").toInt(), 300);
413 QCOMPARE(imgElement.attribute("height"), QString("150"));
414 QCOMPARE(imgElement.attribute("height").toInt(), 150);
415 QCOMPARE(imgElement.attribute("border").isEmpty(), true);
416 QCOMPARE(imgElement.attribute("border", "0").toInt(), 0);
417 QCOMPARE(imgElement.attribute("border", "-1").toInt(), -1);
418
419 QStringList list = KoXml::attributeNames(imgElement);
420 QCOMPARE(list.count(), 3);
421 QVERIFY(list.contains("src"));
422 QVERIFY(list.contains("width"));
423 QVERIFY(list.contains("height"));
424 QVERIFY(! list.contains("border"));
425 foreach(QString a, list) {
426 QCOMPARE(imgElement.hasAttribute(a), true);
427 QCOMPARE(imgElement.attribute(a).isEmpty(), false);
428 }
429 }
430
testText()431 void TestXmlReaderWithoutSpaces::testText()
432 {
433 QString errorMsg;
434 int errorLine = 0;
435 int errorColumn = 0;
436
437 QBuffer xmldevice;
438 xmldevice.open(QIODevice::WriteOnly);
439 QTextStream xmlstream(&xmldevice);
440 xmlstream << "<p>";
441 xmlstream << "Hello ";
442 xmlstream << "<b>world</b>";
443 xmlstream << "</p>";
444 xmldevice.close();
445
446 KoXmlDocument doc(false);
447 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
448 QCOMPARE(errorMsg.isEmpty(), true);
449 QCOMPARE(errorLine, 0);
450 QCOMPARE(errorColumn, 0);
451
452 // element for <p>
453 KoXmlElement parElement;
454 parElement = doc.documentElement();
455 QCOMPARE(parElement.isNull(), false);
456 QCOMPARE(parElement.isElement(), true);
457 QCOMPARE(parElement.isText(), false);
458 QCOMPARE(parElement.isDocument(), false);
459 QCOMPARE(parElement.ownerDocument().isNull(), false);
460 QCOMPARE(parElement.ownerDocument() == doc, true);
461 QCOMPARE(parElement.parentNode().isNull(), false);
462 QCOMPARE(parElement.parentNode().toDocument() == doc, true);
463 QCOMPARE(parElement.hasChildNodes(), true);
464 QCOMPARE(KoXml::childNodesCount(parElement), 2); // <b> and text node "Hello "
465 QCOMPARE(parElement.tagName(), QString("p"));
466 QCOMPARE(parElement.prefix().isNull(), true);
467 QCOMPARE(parElement.text(), QString("Hello world"));
468
469 // node for "Hello"
470 KoXmlNode helloNode;
471 helloNode = parElement.firstChild();
472 QCOMPARE(helloNode.nodeName(), QString("#text"));
473 QCOMPARE(helloNode.isNull(), false);
474 QCOMPARE(helloNode.isElement(), false);
475 QCOMPARE(helloNode.isText(), true);
476 QCOMPARE(helloNode.isDocument(), false);
477 QCOMPARE(helloNode.hasChildNodes(), false);
478 QCOMPARE(KoXml::childNodesCount(helloNode), 0);
479
480 // "Hello" text
481 KoXmlText helloText;
482 helloText = helloNode.toText();
483 QCOMPARE(helloText.nodeName(), QString("#text"));
484 QCOMPARE(helloText.isNull(), false);
485 QCOMPARE(helloText.isElement(), false);
486 QCOMPARE(helloText.isText(), true);
487 QCOMPARE(helloText.isDocument(), false);
488 QCOMPARE(helloText.data(), QString("Hello "));
489 QCOMPARE(KoXml::childNodesCount(helloText), 0);
490
491 // shared copy of the text
492 KoXmlText hello2Text;
493 hello2Text = helloText;
494 QCOMPARE(hello2Text.isNull(), false);
495 QCOMPARE(hello2Text.isElement(), false);
496 QCOMPARE(hello2Text.isText(), true);
497 QCOMPARE(hello2Text.isDocument(), false);
498 QCOMPARE(hello2Text.data(), QString("Hello "));
499 QCOMPARE(KoXml::childNodesCount(hello2Text), 0);
500
501 // element for <b>
502 KoXmlElement boldElement;
503 boldElement = helloNode.nextSibling().toElement();
504 QCOMPARE(boldElement.isNull(), false);
505 QCOMPARE(boldElement.isElement(), true);
506 QCOMPARE(boldElement.isText(), false);
507 QCOMPARE(boldElement.isDocument(), false);
508 QCOMPARE(boldElement.ownerDocument().isNull(), false);
509 QCOMPARE(boldElement.ownerDocument() == doc, true);
510 QCOMPARE(boldElement.parentNode().isNull(), false);
511 QCOMPARE(boldElement.hasChildNodes(), true);
512 QCOMPARE(KoXml::childNodesCount(boldElement), 1); // text node "world"
513 QCOMPARE(boldElement.tagName(), QString("b"));
514 QCOMPARE(boldElement.prefix().isNull(), true);
515
516 // "world" text
517 KoXmlText worldText;
518 worldText = boldElement.firstChild().toText();
519 QCOMPARE(worldText.isNull(), false);
520 QCOMPARE(worldText.isElement(), false);
521 QCOMPARE(worldText.isText(), true);
522 QCOMPARE(worldText.isDocument(), false);
523 QCOMPARE(worldText.data(), QString("world"));
524 QCOMPARE(KoXml::childNodesCount(worldText), 0);
525 }
526
testCDATA()527 void TestXmlReaderWithoutSpaces::testCDATA()
528 {
529 QString errorMsg;
530 int errorLine = 0;
531 int errorColumn = 0;
532
533 QBuffer xmldevice;
534 xmldevice.open(QIODevice::WriteOnly);
535 QTextStream xmlstream(&xmldevice);
536 xmlstream << "<p>";
537 xmlstream << "Hello ";
538 xmlstream << "<![CDATA[world]]>";
539 xmlstream << "</p>";
540 xmldevice.close();
541
542 KoXmlDocument doc(false);
543 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
544 QCOMPARE(errorMsg.isEmpty(), true);
545 QCOMPARE(errorLine, 0);
546 QCOMPARE(errorColumn, 0);
547
548 // element for <p>
549 KoXmlElement parElement;
550 parElement = doc.documentElement();
551 QCOMPARE(parElement.isNull(), false);
552 QCOMPARE(parElement.isElement(), true);
553 QCOMPARE(parElement.isText(), false);
554 QCOMPARE(parElement.isDocument(), false);
555 QCOMPARE(parElement.ownerDocument().isNull(), false);
556 QCOMPARE(parElement.ownerDocument() == doc, true);
557 QCOMPARE(parElement.parentNode().isNull(), false);
558 QCOMPARE(parElement.parentNode().toDocument() == doc, true);
559 QCOMPARE(parElement.hasChildNodes(), true);
560 QCOMPARE(KoXml::childNodesCount(parElement), 2);
561 QCOMPARE(parElement.tagName(), QString("p"));
562 QCOMPARE(parElement.prefix().isNull(), true);
563 QCOMPARE(parElement.text(), QString("Hello world"));
564
565 // node for "Hello"
566 KoXmlNode helloNode;
567 helloNode = parElement.firstChild();
568 QCOMPARE(helloNode.isNull(), false);
569 QCOMPARE(helloNode.isElement(), false);
570 QCOMPARE(helloNode.isText(), true);
571 QCOMPARE(helloNode.isDocument(), false);
572
573 // "Hello" text
574 KoXmlText helloText;
575 helloText = helloNode.toText();
576 QCOMPARE(helloText.isNull(), false);
577 QCOMPARE(helloText.isElement(), false);
578 QCOMPARE(helloText.isText(), true);
579 QCOMPARE(helloText.isDocument(), false);
580 QCOMPARE(helloText.data(), QString("Hello "));
581
582 // node for CDATA "world!"
583 // Note: isText() is also true for CDATA
584 KoXmlNode worldNode;
585 worldNode = helloNode.nextSibling();
586 QCOMPARE(worldNode.nodeName(), QString("#cdata-section"));
587 QCOMPARE(worldNode.isNull(), false);
588 QCOMPARE(worldNode.isElement(), false);
589 QCOMPARE(worldNode.isText(), true);
590 QCOMPARE(worldNode.isCDATASection(), true);
591 QCOMPARE(worldNode.isDocument(), false);
592
593 // CDATA section for "world!"
594 // Note: isText() is also true for CDATA
595 KoXmlCDATASection worldCDATA;
596 worldCDATA = worldNode.toCDATASection();
597 QCOMPARE(worldCDATA.nodeName(), QString("#cdata-section"));
598 QCOMPARE(worldCDATA.isNull(), false);
599 QCOMPARE(worldCDATA.isElement(), false);
600 QCOMPARE(worldCDATA.isText(), true);
601 QCOMPARE(worldCDATA.isCDATASection(), true);
602 QCOMPARE(worldCDATA.isDocument(), false);
603 QCOMPARE(worldCDATA.data(), QString("world"));
604 }
605
testDocument()606 void TestXmlReaderWithoutSpaces::testDocument()
607 {
608 QString errorMsg;
609 int errorLine = 0;
610 int errorColumn = 0;
611
612 QBuffer xmldevice;
613 xmldevice.open(QIODevice::WriteOnly);
614 QTextStream xmlstream(&xmldevice);
615 xmlstream << "<calligra>";
616 xmlstream << "<words/>\n";
617 xmlstream << "<stage/>\n";
618 xmlstream << "</calligra>";
619 xmldevice.close();
620
621 KoXmlDocument doc(false);
622
623 // empty document
624 QCOMPARE(doc.nodeName(), QString());
625 QCOMPARE(doc.isNull(), true);
626 QCOMPARE(doc.isElement(), false);
627 QCOMPARE(doc.isDocument(), false);
628 QCOMPARE(doc.parentNode().isNull(), true);
629 QCOMPARE(doc.firstChild().isNull(), true);
630 QCOMPARE(doc.lastChild().isNull(), true);
631 QCOMPARE(doc.previousSibling().isNull(), true);
632 QCOMPARE(doc.nextSibling().isNull(), true);
633
634 // now give something as the content
635 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
636 QCOMPARE(errorMsg.isEmpty(), true);
637 QCOMPARE(errorLine, 0);
638 QCOMPARE(errorColumn, 0);
639
640 // this document has something already
641 QCOMPARE(doc.nodeName(), QString("#document"));
642 QCOMPARE(doc.isNull(), false);
643 QCOMPARE(doc.isElement(), false);
644 QCOMPARE(doc.isDocument(), true);
645 QCOMPARE(doc.parentNode().isNull(), true);
646 QCOMPARE(doc.firstChild().isNull(), false);
647 QCOMPARE(doc.lastChild().isNull(), false);
648 QCOMPARE(doc.previousSibling().isNull(), true);
649 QCOMPARE(doc.nextSibling().isNull(), true);
650
651 // make sure its children are fine
652 KoXmlElement rootElement;
653 rootElement = doc.firstChild().toElement();
654 QCOMPARE(rootElement.isNull(), false);
655 QCOMPARE(rootElement.isElement(), true);
656 QCOMPARE(rootElement.isDocument(), false);
657 QCOMPARE(rootElement.parentNode().isNull(), false);
658 QCOMPARE(rootElement.parentNode().toDocument() == doc, true);
659 rootElement = doc.lastChild().toElement();
660 QCOMPARE(rootElement.isNull(), false);
661 QCOMPARE(rootElement.isElement(), true);
662 QCOMPARE(rootElement.isDocument(), false);
663 QCOMPARE(rootElement.parentNode().isNull(), false);
664 QCOMPARE(rootElement.parentNode().toDocument() == doc, true);
665
666 // clear() converts it into null node
667 doc.clear();
668 QCOMPARE(doc.nodeName(), QString());
669 QCOMPARE(doc.isNull(), true);
670 QCOMPARE(doc.isElement(), false);
671 QCOMPARE(doc.isDocument(), false);
672 QCOMPARE(doc.parentNode().isNull(), true);
673 QCOMPARE(doc.firstChild().isNull(), true);
674 QCOMPARE(doc.lastChild().isNull(), true);
675 QCOMPARE(doc.previousSibling().isNull(), true);
676 QCOMPARE(doc.nextSibling().isNull(), true);
677
678 // assigned from another empty document
679 doc = KoXmlDocument();
680 QCOMPARE(doc.nodeName(), QString());
681 QCOMPARE(doc.nodeName().isEmpty(), true);
682 QCOMPARE(doc.isNull(), true);
683 QCOMPARE(doc.isElement(), false);
684 QCOMPARE(doc.isDocument(), false);
685 QCOMPARE(doc.parentNode().isNull(), true);
686 }
687
testDocumentType()688 void TestXmlReaderWithoutSpaces::testDocumentType()
689 {
690 QString errorMsg;
691 int errorLine = 0;
692 int errorColumn = 0;
693
694 QBuffer xmldevice;
695 xmldevice.open(QIODevice::WriteOnly);
696 QTextStream xmlstream(&xmldevice);
697 xmlstream << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
698 xmlstream << "<body>";
699 xmlstream << "<img/>";
700 xmlstream << "<p/>";
701 xmlstream << "<blockquote/>";
702 xmlstream << "</body>";
703 xmldevice.close();
704
705 // empty document
706 KoXmlDocument doc(false);
707 QCOMPARE(doc.nodeName(), QString());
708 QCOMPARE(doc.isNull(), true);
709 QCOMPARE(doc.isElement(), false);
710 QCOMPARE(doc.isDocument(), false);
711 QCOMPARE(doc.parentNode().isNull(), true);
712 QCOMPARE(doc.firstChild().isNull(), true);
713 QCOMPARE(doc.lastChild().isNull(), true);
714 QCOMPARE(doc.previousSibling().isNull(), true);
715 QCOMPARE(doc.nextSibling().isNull(), true);
716
717 // has empty doctype
718 KoXmlDocumentType doctype = doc.doctype();
719 QCOMPARE(doctype.nodeName(), QString());
720 QCOMPARE(doctype.isNull(), true);
721 QCOMPARE(doctype.isElement(), false);
722 QCOMPARE(doctype.isDocument(), false);
723 QCOMPARE(doctype.isDocumentType(), false);
724 QCOMPARE(doctype.parentNode().isNull(), true);
725 QCOMPARE(doctype.firstChild().isNull(), true);
726 QCOMPARE(doctype.lastChild().isNull(), true);
727 QCOMPARE(doctype.previousSibling().isNull(), true);
728 QCOMPARE(doctype.nextSibling().isNull(), true);
729
730 // now give something as the content
731 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
732 QCOMPARE(errorMsg.isEmpty(), true);
733 QCOMPARE(errorLine, 0);
734 QCOMPARE(errorColumn, 0);
735
736 // this document has something already
737 QCOMPARE(doc.nodeName(), QString("#document"));
738 QCOMPARE(doc.isNull(), false);
739 QCOMPARE(doc.isElement(), false);
740 QCOMPARE(doc.isDocument(), true);
741 QCOMPARE(doc.parentNode().isNull(), true);
742 QCOMPARE(doc.firstChild().isNull(), false);
743 QCOMPARE(doc.lastChild().isNull(), false);
744 QCOMPARE(doc.previousSibling().isNull(), true);
745 QCOMPARE(doc.nextSibling().isNull(), true);
746
747 // the doctype becomes a valid one
748 doctype = doc.doctype();
749 QCOMPARE(doctype.nodeName(), QString("html"));
750 QCOMPARE(doctype.name(), QString("html"));
751 QCOMPARE(doctype.isNull(), false);
752 QCOMPARE(doctype.isElement(), false);
753 QCOMPARE(doctype.isDocument(), false);
754 QCOMPARE(doctype.isDocumentType(), true);
755 QCOMPARE(doctype.parentNode().isNull(), false);
756 QCOMPARE(doctype.parentNode() == doc, true);
757 QCOMPARE(doctype.firstChild().isNull(), true);
758 QCOMPARE(doctype.lastChild().isNull(), true);
759 QCOMPARE(doctype.previousSibling().isNull(), true);
760 QCOMPARE(doctype.nextSibling().isNull(), true);
761 }
762
testNamespace()763 void TestXmlReaderWithoutSpaces::testNamespace()
764 {
765 QString errorMsg;
766 int errorLine = 0;
767 int errorColumn = 0;
768
769 QBuffer xmldevice;
770 xmldevice.open(QIODevice::WriteOnly);
771 QTextStream xmlstream(&xmldevice);
772
773 // taken from example in Qt documentation (xml.html)
774 xmlstream << "<document xmlns:book = \"http://trolltech.com/fnord/book/\"";
775 xmlstream << " xmlns = \"http://trolltech.com/fnord/\" >";
776 xmlstream << "<book>";
777 xmlstream << "<book:title>Practical XML</book:title>";
778 xmlstream << "<book:author xmlns:fnord = \"http://trolltech.com/fnord/\"";
779 xmlstream << " title=\"Ms\"";
780 xmlstream << " fnord:title=\"Goddess\"";
781 xmlstream << " name=\"Eris Kallisti\"/>";
782 xmlstream << "<chapter>";
783 xmlstream << "<title>A Namespace Called fnord</title>";
784 xmlstream << "</chapter>";
785 xmlstream << "</book>";
786 xmlstream << "</document>";
787 xmldevice.close();
788
789 KoXmlDocument doc(false);
790 KoXmlElement rootElement;
791 KoXmlElement bookElement;
792 KoXmlElement bookTitleElement;
793 KoXmlElement bookAuthorElement;
794
795 // ------------- first without any namespace processing -----------
796 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
797 QCOMPARE(errorMsg.isEmpty(), true);
798 QCOMPARE(errorLine, 0);
799 QCOMPARE(errorColumn, 0);
800
801 rootElement = doc.documentElement();
802 QCOMPARE(rootElement.isNull(), false);
803 QCOMPARE(rootElement.isElement(), true);
804 QCOMPARE(rootElement.tagName(), QString("document"));
805 QCOMPARE(rootElement.prefix().isNull(), true);
806
807 bookElement = rootElement.firstChild().toElement();
808 QCOMPARE(bookElement.isNull(), false);
809 QCOMPARE(bookElement.isElement(), true);
810 QCOMPARE(bookElement.tagName(), QString("book"));
811 QCOMPARE(bookElement.prefix().isNull(), true);
812 QCOMPARE(bookElement.localName(), QString());
813
814 bookTitleElement = bookElement.firstChild().toElement();
815 QCOMPARE(bookTitleElement.isNull(), false);
816 QCOMPARE(bookTitleElement.isElement(), true);
817 QCOMPARE(bookTitleElement.tagName(), QString("book:title"));
818 QCOMPARE(bookTitleElement.prefix().isNull(), true);
819 QCOMPARE(bookTitleElement.localName(), QString());
820
821 bookAuthorElement = bookTitleElement.nextSibling().toElement();
822 QCOMPARE(bookAuthorElement.isNull(), false);
823 QCOMPARE(bookAuthorElement.isElement(), true);
824 QCOMPARE(bookAuthorElement.tagName(), QString("book:author"));
825 QCOMPARE(bookAuthorElement.prefix().isNull(), true);
826 QCOMPARE(bookAuthorElement.attribute("title"), QString("Ms"));
827 QCOMPARE(bookAuthorElement.attribute("fnord:title"), QString("Goddess"));
828 QCOMPARE(bookAuthorElement.attribute("name"), QString("Eris Kallisti"));
829
830 // ------------- now with namespace processing -----------
831 xmldevice.seek(0); // just to rewind
832
833 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
834 QCOMPARE(errorMsg.isEmpty(), true);
835 QCOMPARE(errorLine, 0);
836 QCOMPARE(errorColumn, 0);
837
838 const char* defaultNS = "http://trolltech.com/fnord/";
839 const char* bookNS = "http://trolltech.com/fnord/book/";
840 const char* fnordNS = "http://trolltech.com/fnord/";
841
842 // <document>
843 rootElement = doc.documentElement();
844 QCOMPARE(rootElement.isNull(), false);
845 QCOMPARE(rootElement.isElement(), true);
846 QCOMPARE(rootElement.tagName(), QString("document"));
847 QCOMPARE(rootElement.prefix().isEmpty(), true);
848 QCOMPARE(rootElement.namespaceURI(), QString(defaultNS));
849 QCOMPARE(rootElement.localName(), QString("document"));
850
851 // <book>
852 bookElement = rootElement.firstChild().toElement();
853 QCOMPARE(bookElement.isNull(), false);
854 QCOMPARE(bookElement.isElement(), true);
855 QCOMPARE(bookElement.tagName(), QString("book"));
856 QCOMPARE(bookElement.prefix().isEmpty(), true);
857 QCOMPARE(bookElement.namespaceURI(), QString(defaultNS));
858 QCOMPARE(bookElement.localName(), QString("book"));
859
860 // <book:title>
861 bookTitleElement = bookElement.firstChild().toElement();
862 QCOMPARE(bookTitleElement.isNull(), false);
863 QCOMPARE(bookTitleElement.isElement(), true);
864 QCOMPARE(bookTitleElement.tagName(), QString("title"));
865 QCOMPARE(bookTitleElement.prefix(), QString("book"));
866 QCOMPARE(bookTitleElement.namespaceURI(), QString(bookNS));
867 QCOMPARE(bookTitleElement.localName(), QString("title"));
868
869 // another way, find it using namedItemNS()
870 KoXmlElement book2TitleElement;
871 book2TitleElement = KoXml::namedItemNS(rootElement.firstChild(), bookNS, "title");
872 //book2TitleElement = bookElement.namedItemNS( bookNS, "title" ).toElement();
873 QCOMPARE(book2TitleElement == bookTitleElement, true);
874 QCOMPARE(book2TitleElement.isNull(), false);
875 QCOMPARE(book2TitleElement.isElement(), true);
876 QCOMPARE(book2TitleElement.tagName(), QString("title"));
877
878 // <book:author>
879 bookAuthorElement = bookTitleElement.nextSibling().toElement();
880 QCOMPARE(bookAuthorElement.isNull(), false);
881 QCOMPARE(bookAuthorElement.isElement(), true);
882 QCOMPARE(bookAuthorElement.tagName(), QString("author"));
883 QCOMPARE(bookAuthorElement.prefix(), QString("book"));
884 QCOMPARE(bookAuthorElement.namespaceURI(), QString(bookNS));
885 QCOMPARE(bookAuthorElement.localName(), QString("author"));
886
887 // another way, find it using namedItemNS()
888 KoXmlElement book2AuthorElement;
889 book2AuthorElement = KoXml::namedItemNS(bookElement, bookNS, "author");
890 //book2AuthorElement = bookElement.namedItemNS( bookNS, "author" ).toElement();
891 QCOMPARE(book2AuthorElement == bookAuthorElement, true);
892 QCOMPARE(book2AuthorElement.isNull(), false);
893 QCOMPARE(book2AuthorElement.isElement(), true);
894 QCOMPARE(book2AuthorElement.tagName(), QString("author"));
895
896 // attributes in <book:author>
897 // Note: with namespace processing, attribute's prefix is taken out and
898 // hence "fnord:title" will simply override "title"
899 // and searching attribute with prefix will give no result
900 QCOMPARE(bookAuthorElement.hasAttribute("title"), true);
901 QCOMPARE(bookAuthorElement.hasAttribute("fnord:title"), false);
902 QCOMPARE(bookAuthorElement.hasAttribute("name"), true);
903 QCOMPARE(bookAuthorElement.attribute("title"), QString("Goddess"));
904 QCOMPARE(bookAuthorElement.attribute("fnord:title").isEmpty(), true);
905 QCOMPARE(bookAuthorElement.attribute("name"), QString("Eris Kallisti"));
906
907 // attributes in <book:author>, with NS family of functions
908 // those without prefix are not accessible at all, because they do not belong
909 // to any namespace at all.
910 // Note: default namespace does not apply to attribute names!
911 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "title"), true);
912 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "title"), false);
913 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "title"), true);
914
915 QCOMPARE(bookAuthorElement.attributeNS(defaultNS, "title", ""), QString("Goddess"));
916 QCOMPARE(bookAuthorElement.attributeNS(bookNS, "title", ""), QString(""));
917 QCOMPARE(bookAuthorElement.attributeNS(fnordNS, "title", ""), QString("Goddess"));
918
919 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "fnord:title"), false);
920 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "fnord:title"), false);
921 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "fnord:title"), false);
922
923 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "name"), false);
924 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "name"), false);
925 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "name"), false);
926
927 QCOMPARE(bookAuthorElement.attributeNS(defaultNS, "name", QString()).isEmpty(), true);
928 QCOMPARE(bookAuthorElement.attributeNS(bookNS, "name", QString()).isEmpty(), true);
929 QCOMPARE(bookAuthorElement.attributeNS(fnordNS, "name", QString()).isEmpty(), true);
930 }
931
932 // mostly similar to testNamespace above, but parse from a QString
testParseQString()933 void TestXmlReaderWithoutSpaces::testParseQString()
934 {
935 QString errorMsg;
936 int errorLine = 0;
937 int errorColumn = 0;
938
939 QString xmlText;
940 xmlText += "<document xmlns:book = \"http://trolltech.com/fnord/book/\"";
941 xmlText += " xmlns = \"http://trolltech.com/fnord/\" >";
942 xmlText += "<book>";
943 xmlText += "<book:title>Practical XML</book:title>";
944 xmlText += "<book:author xmlns:fnord = \"http://trolltech.com/fnord/\"";
945 xmlText += " title=\"Ms\"";
946 xmlText += " fnord:title=\"Goddess\"";
947 xmlText += " name=\"Eris Kallisti\"/>";
948 xmlText += "<chapter>";
949 xmlText += "<title>A Namespace Called fnord</title>";
950 xmlText += "</chapter>";
951 xmlText += "</book>";
952 xmlText += "</document>";
953
954 KoXmlDocument doc(false);
955 KoXmlElement rootElement;
956 KoXmlElement bookElement;
957 KoXmlElement bookTitleElement;
958 KoXmlElement bookAuthorElement;
959
960 QCOMPARE(doc.setContent(xmlText, true, &errorMsg, &errorLine, &errorColumn), true);
961 QCOMPARE(errorMsg.isEmpty(), true);
962 QCOMPARE(errorLine, 0);
963 QCOMPARE(errorColumn, 0);
964
965 const char* defaultNS = "http://trolltech.com/fnord/";
966 const char* bookNS = "http://trolltech.com/fnord/book/";
967 const char* fnordNS = "http://trolltech.com/fnord/";
968
969 // <document>
970 rootElement = doc.documentElement();
971 QCOMPARE(rootElement.isNull(), false);
972 QCOMPARE(rootElement.isElement(), true);
973 QCOMPARE(rootElement.tagName(), QString("document"));
974 QCOMPARE(rootElement.prefix().isEmpty(), true);
975 QCOMPARE(rootElement.namespaceURI(), QString(defaultNS));
976 QCOMPARE(rootElement.localName(), QString("document"));
977
978 // <book>
979 bookElement = rootElement.firstChild().toElement();
980 QCOMPARE(bookElement.isNull(), false);
981 QCOMPARE(bookElement.isElement(), true);
982 QCOMPARE(bookElement.tagName(), QString("book"));
983 QCOMPARE(bookElement.prefix().isEmpty(), true);
984 QCOMPARE(bookElement.namespaceURI(), QString(defaultNS));
985 QCOMPARE(bookElement.localName(), QString("book"));
986
987 // <book:title>
988 bookTitleElement = bookElement.firstChild().toElement();
989 QCOMPARE(bookTitleElement.isNull(), false);
990 QCOMPARE(bookTitleElement.isElement(), true);
991 QCOMPARE(bookTitleElement.tagName(), QString("title"));
992 QCOMPARE(bookTitleElement.prefix(), QString("book"));
993 QCOMPARE(bookTitleElement.namespaceURI(), QString(bookNS));
994 QCOMPARE(bookTitleElement.localName(), QString("title"));
995
996 // another way, find it using namedItemNS()
997 KoXmlElement book2TitleElement;
998 book2TitleElement = KoXml::namedItemNS(rootElement.firstChild(), bookNS, "title");
999 //book2TitleElement = bookElement.namedItemNS( bookNS, "title" ).toElement();
1000 QCOMPARE(book2TitleElement == bookTitleElement, true);
1001 QCOMPARE(book2TitleElement.isNull(), false);
1002 QCOMPARE(book2TitleElement.isElement(), true);
1003 QCOMPARE(book2TitleElement.tagName(), QString("title"));
1004
1005 // <book:author>
1006 bookAuthorElement = bookTitleElement.nextSibling().toElement();
1007 QCOMPARE(bookAuthorElement.isNull(), false);
1008 QCOMPARE(bookAuthorElement.isElement(), true);
1009 QCOMPARE(bookAuthorElement.tagName(), QString("author"));
1010 QCOMPARE(bookAuthorElement.prefix(), QString("book"));
1011 QCOMPARE(bookAuthorElement.namespaceURI(), QString(bookNS));
1012 QCOMPARE(bookAuthorElement.localName(), QString("author"));
1013
1014 // another way, find it using namedItemNS()
1015 KoXmlElement book2AuthorElement;
1016 book2AuthorElement = KoXml::namedItemNS(bookElement, bookNS, "author");
1017 //book2AuthorElement = bookElement.namedItemNS( bookNS, "author" ).toElement();
1018 QCOMPARE(book2AuthorElement == bookAuthorElement, true);
1019 QCOMPARE(book2AuthorElement.isNull(), false);
1020 QCOMPARE(book2AuthorElement.isElement(), true);
1021 QCOMPARE(book2AuthorElement.tagName(), QString("author"));
1022
1023 // attributes in <book:author>
1024 // Note: with namespace processing, attribute's prefix is taken out and
1025 // hence "fnord:title" will simply override "title"
1026 // and searching attribute with prefix will give no result
1027 QCOMPARE(bookAuthorElement.hasAttribute("title"), true);
1028 QCOMPARE(bookAuthorElement.hasAttribute("fnord:title"), false);
1029 QCOMPARE(bookAuthorElement.hasAttribute("name"), true);
1030 QCOMPARE(bookAuthorElement.attribute("title"), QString("Goddess"));
1031 QCOMPARE(bookAuthorElement.attribute("fnord:title").isEmpty(), true);
1032 QCOMPARE(bookAuthorElement.attribute("name"), QString("Eris Kallisti"));
1033
1034 // attributes in <book:author>, with NS family of functions
1035 // those without prefix are not accessible at all, because they do not belong
1036 // to any namespace at all.
1037 // Note: default namespace does not apply to attribute names!
1038 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "title"), true);
1039 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "title"), false);
1040 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "title"), true);
1041
1042 QCOMPARE(bookAuthorElement.attributeNS(defaultNS, "title", ""), QString("Goddess"));
1043 QCOMPARE(bookAuthorElement.attributeNS(bookNS, "title", ""), QString(""));
1044 QCOMPARE(bookAuthorElement.attributeNS(fnordNS, "title", ""), QString("Goddess"));
1045
1046 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "fnord:title"), false);
1047 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "fnord:title"), false);
1048 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "fnord:title"), false);
1049
1050 QCOMPARE(bookAuthorElement.hasAttributeNS(defaultNS, "name"), false);
1051 QCOMPARE(bookAuthorElement.hasAttributeNS(bookNS, "name"), false);
1052 QCOMPARE(bookAuthorElement.hasAttributeNS(fnordNS, "name"), false);
1053
1054 QCOMPARE(bookAuthorElement.attributeNS(defaultNS, "name", QString()).isEmpty(), true);
1055 QCOMPARE(bookAuthorElement.attributeNS(bookNS, "name", QString()).isEmpty(), true);
1056 QCOMPARE(bookAuthorElement.attributeNS(fnordNS, "name", QString()).isEmpty(), true);
1057 }
1058
testUnload()1059 void TestXmlReaderWithoutSpaces::testUnload()
1060 {
1061 QString errorMsg;
1062 int errorLine = 0;
1063 int errorColumn = 0;
1064
1065 QBuffer xmldevice;
1066 xmldevice.open(QIODevice::WriteOnly);
1067 QTextStream xmlstream(&xmldevice);
1068
1069 xmlstream << "<earth>";
1070 xmlstream << "<continents>";
1071 xmlstream << "<asia/>";
1072 xmlstream << "<africa/>";
1073 xmlstream << "<europe/>";
1074 xmlstream << "<america/>";
1075 xmlstream << "<australia/>";
1076 xmlstream << "<antartic/>";
1077 xmlstream << "</continents>";
1078 xmlstream << "<oceans>";
1079 xmlstream << "<pacific/>";
1080 xmlstream << "<atlantic/>";
1081 xmlstream << "</oceans>";
1082 xmlstream << "</earth>";
1083 xmldevice.close();
1084
1085 KoXmlDocument doc(false);
1086 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
1087 QCOMPARE(errorMsg.isEmpty(), true);
1088 QCOMPARE(errorLine, 0);
1089 QCOMPARE(errorColumn, 0);
1090
1091 KoXmlElement earthElement;
1092 earthElement = doc.documentElement().toElement();
1093 QCOMPARE(earthElement.isNull(), false);
1094 QCOMPARE(earthElement.isElement(), true);
1095 QCOMPARE(earthElement.parentNode().isNull(), false);
1096 QCOMPARE(earthElement.hasChildNodes(), true);
1097 QCOMPARE(KoXml::childNodesCount(earthElement), 2);
1098 QCOMPARE(earthElement.tagName(), QString("earth"));
1099 QCOMPARE(earthElement.prefix().isNull(), true);
1100
1101 // this ensures that all child nodes of <earth> are loaded
1102 earthElement.firstChild();
1103
1104 // explicitly unload all child nodes of <earth>
1105 KoXml::unload(earthElement);
1106
1107 // we should get the correct first child
1108 KoXmlElement continentsElement = earthElement.firstChild().toElement();
1109 QCOMPARE(continentsElement.nodeName(), QString("continents"));
1110 QCOMPARE(continentsElement.isNull(), false);
1111 QCOMPARE(continentsElement.isElement(), true);
1112 QCOMPARE(continentsElement.isText(), false);
1113 QCOMPARE(continentsElement.isDocument(), false);
1114 QCOMPARE(continentsElement.hasChildNodes(), true);
1115 QCOMPARE(KoXml::childNodesCount(continentsElement), 6);
1116
1117 // let us unload everything again
1118 KoXml::unload(earthElement);
1119
1120 // we should get the correct last child
1121 KoXmlElement oceansElement = earthElement.lastChild().toElement();
1122 QCOMPARE(oceansElement.nodeName(), QString("oceans"));
1123 QCOMPARE(oceansElement.isNull(), false);
1124 QCOMPARE(oceansElement.isElement(), true);
1125 QCOMPARE(oceansElement.isText(), false);
1126 QCOMPARE(oceansElement.isDocument(), false);
1127 QCOMPARE(oceansElement.hasChildNodes(), true);
1128 QCOMPARE(KoXml::childNodesCount(continentsElement), 6);
1129 }
1130
testSimpleXML()1131 void TestXmlReaderWithoutSpaces::testSimpleXML()
1132 {
1133 QString errorMsg;
1134 int errorLine = 0;
1135 int errorColumn = 0;
1136
1137 QBuffer xmldevice;
1138 xmldevice.open(QIODevice::WriteOnly);
1139 QTextStream xmlstream(&xmldevice);
1140 xmlstream << "<solarsystem>";
1141 xmlstream << "<mercurius/>";
1142 xmlstream << "<venus/>";
1143 xmlstream << "<earth>";
1144 xmlstream << "<moon/>";
1145 xmlstream << "</earth>";
1146 xmlstream << "<mars/>";
1147 xmlstream << "<jupiter/>";
1148 xmlstream << "</solarsystem>";
1149 xmldevice.close();
1150
1151 KoXmlDocument doc(false);
1152 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
1153 QCOMPARE(errorMsg.isEmpty(), true);
1154 QCOMPARE(errorLine, 0);
1155 QCOMPARE(errorColumn, 0);
1156
1157 // <solarsystem>
1158 KoXmlElement rootElement;
1159 rootElement = doc.documentElement();
1160 QCOMPARE(rootElement.isNull(), false);
1161 QCOMPARE(rootElement.isElement(), true);
1162 QCOMPARE(rootElement.parentNode().isNull(), false);
1163 QCOMPARE(rootElement.hasChildNodes(), true);
1164 QCOMPARE(KoXml::childNodesCount(rootElement), 5);
1165 QCOMPARE(rootElement.tagName(), QString("solarsystem"));
1166 QCOMPARE(rootElement.prefix().isNull(), true);
1167
1168 // node <mercurius>
1169 KoXmlNode firstPlanetNode;
1170 firstPlanetNode = rootElement.firstChild();
1171 QCOMPARE(firstPlanetNode.isNull(), false);
1172 QCOMPARE(firstPlanetNode.isElement(), true);
1173 QCOMPARE(firstPlanetNode.nextSibling().isNull(), false);
1174 QCOMPARE(firstPlanetNode.previousSibling().isNull(), true);
1175 QCOMPARE(firstPlanetNode.parentNode().isNull(), false);
1176 QCOMPARE(firstPlanetNode.parentNode() == rootElement, true);
1177 QCOMPARE(firstPlanetNode.parentNode() != rootElement, false);
1178 QCOMPARE(firstPlanetNode.hasChildNodes(), false);
1179 QCOMPARE(KoXml::childNodesCount(firstPlanetNode), 0);
1180 QCOMPARE(firstPlanetNode.firstChild().isNull(), true);
1181 QCOMPARE(firstPlanetNode.lastChild().isNull(), true);
1182
1183 // element <mercurius>
1184 KoXmlElement firstPlanetElement;
1185 firstPlanetElement = firstPlanetNode.toElement();
1186 QCOMPARE(firstPlanetElement.isNull(), false);
1187 QCOMPARE(firstPlanetElement.isElement(), true);
1188 QCOMPARE(firstPlanetElement.parentNode().isNull(), false);
1189 QCOMPARE(firstPlanetElement.parentNode() == rootElement, true);
1190 QCOMPARE(firstPlanetElement.hasChildNodes(), false);
1191 QCOMPARE(KoXml::childNodesCount(firstPlanetNode), 0);
1192 QCOMPARE(firstPlanetElement.firstChild().isNull(), true);
1193 QCOMPARE(firstPlanetElement.lastChild().isNull(), true);
1194 QCOMPARE(firstPlanetElement.tagName(), QString("mercurius"));
1195 QCOMPARE(firstPlanetElement.prefix().isNull(), true);
1196
1197 // node <venus>
1198 KoXmlNode secondPlanetNode;
1199 secondPlanetNode = firstPlanetNode.nextSibling();
1200 QCOMPARE(secondPlanetNode.isNull(), false);
1201 QCOMPARE(secondPlanetNode.isElement(), true);
1202 QCOMPARE(secondPlanetNode.nextSibling().isNull(), false);
1203 QCOMPARE(secondPlanetNode.previousSibling().isNull(), false);
1204 QCOMPARE(secondPlanetNode.previousSibling() == firstPlanetNode, true);
1205 QCOMPARE(secondPlanetNode.previousSibling() == firstPlanetElement, true);
1206 QCOMPARE(secondPlanetNode.parentNode().isNull(), false);
1207 QCOMPARE(secondPlanetNode.parentNode() == rootElement, true);
1208 QCOMPARE(secondPlanetNode.parentNode() != rootElement, false);
1209 QCOMPARE(secondPlanetNode.hasChildNodes(), false);
1210 QCOMPARE(KoXml::childNodesCount(secondPlanetNode), 0);
1211 QCOMPARE(secondPlanetNode.firstChild().isNull(), true);
1212 QCOMPARE(secondPlanetNode.lastChild().isNull(), true);
1213
1214 // element <venus>
1215 KoXmlElement secondPlanetElement;
1216 secondPlanetElement = secondPlanetNode.toElement();
1217 QCOMPARE(secondPlanetElement.isNull(), false);
1218 QCOMPARE(secondPlanetElement.isElement(), true);
1219 QCOMPARE(secondPlanetElement.nextSibling().isNull(), false);
1220 QCOMPARE(secondPlanetElement.previousSibling().isNull(), false);
1221 QCOMPARE(secondPlanetElement.previousSibling() == firstPlanetNode, true);
1222 QCOMPARE(secondPlanetElement.previousSibling() == firstPlanetElement, true);
1223 QCOMPARE(secondPlanetElement.parentNode().isNull(), false);
1224 QCOMPARE(secondPlanetElement.parentNode() == rootElement, true);
1225 QCOMPARE(secondPlanetElement.parentNode() != rootElement, false);
1226 QCOMPARE(secondPlanetElement.hasChildNodes(), false);
1227 QCOMPARE(KoXml::childNodesCount(secondPlanetNode), 0);
1228 QCOMPARE(secondPlanetElement.firstChild().isNull(), true);
1229 QCOMPARE(secondPlanetElement.lastChild().isNull(), true);
1230 QCOMPARE(secondPlanetElement.tagName(), QString("venus"));
1231 QCOMPARE(secondPlanetElement.prefix().isNull(), true);
1232 }
1233
testRootError()1234 void TestXmlReaderWithoutSpaces::testRootError()
1235 {
1236 QString errorMsg;
1237 int errorLine = 0;
1238 int errorColumn = 0;
1239
1240 // multiple root nodes are not valid !
1241 QBuffer xmldevice;
1242 xmldevice.open(QIODevice::WriteOnly);
1243 QTextStream xmlstream(&xmldevice);
1244 xmlstream << "<earth></earth><moon></moon>";
1245 xmldevice.close();
1246
1247 KoXmlDocument doc(false);
1248 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), false);
1249 QCOMPARE(errorMsg.isEmpty(), false);
1250 QCOMPARE(errorMsg, QCoreApplication::translate("QXmlStream", "Extra content at end of document."));
1251 QCOMPARE(errorLine, 1);
1252 QCOMPARE(errorColumn, 21);
1253 }
1254
testMismatchedTag()1255 void TestXmlReaderWithoutSpaces::testMismatchedTag()
1256 {
1257 QString errorMsg;
1258 int errorLine = 0;
1259 int errorColumn = 0;
1260
1261 QBuffer xmldevice;
1262 xmldevice.open(QIODevice::WriteOnly);
1263 QTextStream xmlstream(&xmldevice);
1264 xmlstream << "<earth></e>";
1265 xmldevice.close();
1266
1267 KoXmlDocument doc(false);
1268 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), false);
1269 QCOMPARE(errorMsg.isEmpty(), false);
1270 QCOMPARE(errorMsg, QCoreApplication::translate("QXmlStream", "Opening and ending tag mismatch."));
1271 QCOMPARE(errorLine, 1);
1272 QCOMPARE(errorColumn, 11);
1273 }
1274
dumpNodes(const KoXmlNode & node,int level=0)1275 static void dumpNodes(const KoXmlNode &node, int level=0)
1276 {
1277 QString indent = QString("%1").arg("", level*3);
1278 if (node.isNull()) {
1279 qDebug()<<indent<<"null";
1280 }
1281 qDebug()<<indent<<node.nodeName();
1282 for(KoXmlNode n = node.firstChild(); ! n.isNull(); n = n.nextSibling() ) {
1283 dumpNodes(n, level+1);
1284 }
1285
1286 }
dumpNodes(const QDomNode & node,int level=0)1287 static void dumpNodes(const QDomNode &node, int level=0)
1288 {
1289 QString indent = QString("%1").arg("", level*3);
1290 if (node.isNull()) {
1291 qDebug()<<indent<<"null";
1292 }
1293 qDebug()<<indent<<node.nodeName();
1294 for(QDomNode n = node.firstChild(); ! n.isNull(); n = n.nextSibling() ) {
1295 dumpNodes(n, level+1);
1296 }
1297
1298 }
testConvertQDomDocument()1299 void TestXmlReaderWithoutSpaces::testConvertQDomDocument()
1300 {
1301 QString errorMsg;
1302 int errorLine = 0;
1303 int errorColumn = 0;
1304
1305 QBuffer xmldevice;
1306 xmldevice.open(QIODevice::WriteOnly);
1307 QTextStream xmlstream(&xmldevice);
1308 xmlstream << "<solarsystem star=\"sun\">";
1309 xmlstream << "<mercurius/>";
1310 xmlstream << "<venus/>";
1311 xmlstream << "<earth habitable=\"true\"><p>The best place</p>";
1312 xmlstream << "<moon habitable=\"possible\"/>";
1313 xmlstream << "</earth>";
1314 xmlstream << "<mars/>";
1315 xmlstream << "<jupiter/>";
1316 xmlstream << "</solarsystem>";
1317 xmldevice.close();
1318
1319 KoXmlDocument doc(false);
1320 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
1321 QCOMPARE(errorMsg.isEmpty(), true);
1322 QCOMPARE(errorLine, 0);
1323 QCOMPARE(errorColumn, 0);
1324
1325 dumpNodes(doc);
1326 // <solarsystem>
1327 KoXmlElement rootElement;
1328 rootElement = doc.documentElement();
1329 QCOMPARE(rootElement.isNull(), false);
1330 QCOMPARE(rootElement.isElement(), true);
1331 QCOMPARE(rootElement.parentNode().isNull(), false);
1332 QCOMPARE(rootElement.hasChildNodes(), true);
1333 QCOMPARE(KoXml::childNodesCount(rootElement), 5);
1334 QCOMPARE(rootElement.tagName(), QString("solarsystem"));
1335 QCOMPARE(rootElement.prefix().isNull(), true);
1336
1337 // now test converting KoXmlDocument to QDomDocument
1338 QDomDocument universeDoc = KoXml::asQDomDocument(doc);
1339
1340 // <solarsystem>
1341 QDomElement solarSystemElement = universeDoc.documentElement();
1342 QCOMPARE(solarSystemElement.isNull(), false);
1343 QCOMPARE(solarSystemElement.isElement(), true);
1344 QCOMPARE(solarSystemElement.parentNode().isNull(), false);
1345 QCOMPARE(solarSystemElement.hasChildNodes(), true);
1346 QCOMPARE(solarSystemElement.tagName(), QString("solarsystem"));
1347 QCOMPARE(solarSystemElement.prefix().isNull(), true);
1348
1349 // <earth>
1350 QDomElement earthElement = solarSystemElement.namedItem("earth").toElement();
1351 QCOMPARE(earthElement.isNull(), false);
1352 QCOMPARE(earthElement.isElement(), true);
1353 QCOMPARE(earthElement.parentNode().isNull(), false);
1354 QCOMPARE(earthElement.hasAttribute("habitable"), true);
1355 QCOMPARE(earthElement.hasChildNodes(), true);
1356 QCOMPARE(earthElement.tagName(), QString("earth"));
1357 QCOMPARE(earthElement.prefix().isNull(), true);
1358
1359 // <p> in <earth>
1360 QDomNode placeNode = earthElement.firstChild();
1361 qDebug()<<"placeNode"<<placeNode.nodeName();
1362 dumpNodes(placeNode);
1363 QCOMPARE(placeNode.isNull(), false);
1364 QCOMPARE(placeNode.isElement(), true);
1365 QCOMPARE(placeNode.toElement().text(), QString("The best place"));
1366 QCOMPARE(placeNode.nextSibling().isNull(), false);
1367 QCOMPARE(placeNode.previousSibling().isNull(), true);
1368 QCOMPARE(placeNode.parentNode().isNull(), false);
1369 QCOMPARE(placeNode.parentNode() == earthElement, true);
1370 QCOMPARE(placeNode.hasChildNodes(), true);
1371 QCOMPARE(placeNode.childNodes().count(), 1);
1372
1373 //printf("Result:\n%s\n\n", qPrintable(universeDoc.toString()));
1374 }
1375
testConvertQDomElement()1376 void TestXmlReaderWithoutSpaces::testConvertQDomElement()
1377 {
1378 QString errorMsg;
1379 int errorLine = 0;
1380 int errorColumn = 0;
1381
1382 QBuffer xmldevice;
1383 xmldevice.open(QIODevice::WriteOnly);
1384 QTextStream xmlstream(&xmldevice);
1385 xmlstream << "<universe>";
1386 xmlstream << "<solarsystem star=\"sun\">";
1387 xmlstream << "<mercurius/>";
1388 xmlstream << "<venus/>";
1389 xmlstream << "<earth habitable=\"true\"><p>The best place</p>";
1390 xmlstream << "<moon habitable=\"possible\"/>";
1391 xmlstream << "</earth>";
1392 xmlstream << "<mars/>";
1393 xmlstream << "<jupiter/>";
1394 xmlstream << "</solarsystem>";
1395 xmlstream << "</universe>";
1396 xmldevice.close();
1397
1398 KoXmlDocument doc(false);
1399 QCOMPARE(doc.setContent(&xmldevice, &errorMsg, &errorLine, &errorColumn), true);
1400 QCOMPARE(errorMsg.isEmpty(), true);
1401 QCOMPARE(errorLine, 0);
1402 QCOMPARE(errorColumn, 0);
1403
1404 // <solarsystem>
1405 KoXmlElement rootElement;
1406 rootElement = doc.documentElement();
1407 QCOMPARE(rootElement.isNull(), false);
1408 QCOMPARE(rootElement.isElement(), true);
1409 QCOMPARE(rootElement.parentNode().isNull(), false);
1410 QCOMPARE(rootElement.hasChildNodes(), true);
1411 QCOMPARE(KoXml::childNodesCount(rootElement), 1);
1412 QCOMPARE(rootElement.tagName(), QString("universe"));
1413 QCOMPARE(rootElement.prefix().isNull(), true);
1414
1415 // now test converting KoXmlElement to QDomElement
1416 QDomDocument solarDoc;
1417 KoXml::asQDomElement(solarDoc, rootElement.firstChild().toElement());
1418
1419 // <solarsystem>
1420 QDomElement solarSystemElement = solarDoc.documentElement();
1421 QCOMPARE(solarSystemElement.isNull(), false);
1422 QCOMPARE(solarSystemElement.isElement(), true);
1423 QCOMPARE(solarSystemElement.parentNode().isNull(), false);
1424 QCOMPARE(solarSystemElement.hasChildNodes(), true);
1425 QCOMPARE(solarSystemElement.tagName(), QString("solarsystem"));
1426 QCOMPARE(solarSystemElement.prefix().isNull(), true);
1427
1428 // <earth>
1429 QDomElement earthElement = solarSystemElement.namedItem("earth").toElement();
1430 QCOMPARE(earthElement.isNull(), false);
1431 QCOMPARE(earthElement.isElement(), true);
1432 QCOMPARE(earthElement.parentNode().isNull(), false);
1433 QCOMPARE(earthElement.hasAttribute("habitable"), true);
1434 QCOMPARE(earthElement.hasChildNodes(), true);
1435 QCOMPARE(earthElement.tagName(), QString("earth"));
1436 QCOMPARE(earthElement.prefix().isNull(), true);
1437
1438 // <p> in <earth>
1439 QDomNode placeNode = earthElement.firstChild();
1440 QCOMPARE(placeNode.isNull(), false);
1441 QCOMPARE(placeNode.isElement(), true);
1442 QCOMPARE(placeNode.toElement().text(), QString("The best place"));
1443 QCOMPARE(placeNode.nextSibling().isNull(), false);
1444 QCOMPARE(placeNode.previousSibling().isNull(), true);
1445 QCOMPARE(placeNode.parentNode().isNull(), false);
1446 QCOMPARE(placeNode.parentNode() == earthElement, true);
1447 QCOMPARE(placeNode.hasChildNodes(), true);
1448 QCOMPARE(placeNode.childNodes().count(), 1);
1449
1450 //printf("Result:\n%s\n\n", qPrintable(universeDoc.toString()));
1451 }
1452
1453
testSimpleOpenDocumentText()1454 void TestXmlReaderWithoutSpaces::testSimpleOpenDocumentText()
1455 {
1456 QString errorMsg;
1457 int errorLine = 0;
1458 int errorColumn = 0;
1459
1460 QBuffer xmldevice;
1461 xmldevice.open(QIODevice::WriteOnly);
1462 QTextStream xmlstream(&xmldevice);
1463
1464 // content.xml from a simple OpenDocument text
1465 // it has only paragraph "Hello, world!"
1466 // automatic styles, declarations and unnecessary namespaces are omitted.
1467 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1468 xmlstream << "<office:document-content ";
1469 xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
1470 xmlstream << " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"";
1471 xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
1472 xmlstream << " office:version=\"1.0\">";
1473 xmlstream << "<office:automatic-styles/>";
1474 xmlstream << "<office:body>";
1475 xmlstream << "<office:text>";
1476 xmlstream << "<text:p text:style-name=\"Standard\">Hello, world!</text:p>";
1477 xmlstream << "</office:text>";
1478 xmlstream << "</office:body>";
1479 xmlstream << "</office:document-content>";
1480 xmldevice.close();
1481
1482 KoXmlDocument doc(false);
1483 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
1484 QCOMPARE(errorMsg.isEmpty(), true);
1485 QCOMPARE(errorLine, 0);
1486 QCOMPARE(errorColumn, 0);
1487
1488 const char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
1489 const char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
1490
1491 // <office:document-content>
1492 KoXmlElement contentElement;
1493 contentElement = doc.documentElement();
1494 QCOMPARE(contentElement.isNull(), false);
1495 QCOMPARE(contentElement.isElement(), true);
1496 QCOMPARE(contentElement.parentNode().isNull(), false);
1497 QCOMPARE(contentElement.parentNode().toDocument() == doc, true);
1498 QCOMPARE(KoXml::childNodesCount(contentElement), 2);
1499 QCOMPARE(contentElement.firstChild().isNull(), false);
1500 QCOMPARE(contentElement.lastChild().isNull(), false);
1501 QCOMPARE(contentElement.previousSibling().isNull(), false);
1502 QCOMPARE(contentElement.nextSibling().isNull(), true);
1503 QCOMPARE(contentElement.localName(), QString("document-content"));
1504 QCOMPARE(contentElement.hasAttributeNS(officeNS, "version"), true);
1505 QCOMPARE(contentElement.attributeNS(officeNS, "version", ""), QString("1.0"));
1506
1507 // <office:automatic-styles>
1508 KoXmlElement stylesElement;
1509 stylesElement = KoXml::namedItemNS(contentElement, officeNS, "automatic-styles");
1510 QCOMPARE(stylesElement.isNull(), false);
1511 QCOMPARE(stylesElement.isElement(), true);
1512 QCOMPARE(stylesElement.parentNode().isNull(), false);
1513 QCOMPARE(stylesElement.parentNode() == contentElement, true);
1514 QCOMPARE(KoXml::childNodesCount(stylesElement), 0);
1515 QCOMPARE(stylesElement.firstChild().isNull(), true);
1516 QCOMPARE(stylesElement.lastChild().isNull(), true);
1517 QCOMPARE(stylesElement.previousSibling().isNull(), true);
1518 QCOMPARE(stylesElement.nextSibling().isNull(), false);
1519 QCOMPARE(stylesElement.localName(), QString("automatic-styles"));
1520
1521 // also same <office:automatic-styles>, but without namedItemNS
1522 KoXmlNode styles2Element;
1523 styles2Element = contentElement.firstChild().toElement();
1524 QCOMPARE(styles2Element.isNull(), false);
1525 QCOMPARE(styles2Element.isElement(), true);
1526 QCOMPARE(styles2Element.parentNode().isNull(), false);
1527 QCOMPARE(styles2Element.parentNode() == contentElement, true);
1528 QCOMPARE(KoXml::childNodesCount(styles2Element), 0);
1529 QCOMPARE(styles2Element.firstChild().isNull(), true);
1530 QCOMPARE(styles2Element.lastChild().isNull(), true);
1531 QCOMPARE(styles2Element.previousSibling().isNull(), true);
1532 QCOMPARE(styles2Element.nextSibling().isNull(), false);
1533 QCOMPARE(styles2Element.localName(), QString("automatic-styles"));
1534
1535 // <office:body>
1536 KoXmlElement bodyElement;
1537 bodyElement = KoXml::namedItemNS(contentElement, officeNS, "body");
1538 QCOMPARE(bodyElement.isNull(), false);
1539 QCOMPARE(bodyElement.isElement(), true);
1540 QCOMPARE(bodyElement.parentNode().isNull(), false);
1541 QCOMPARE(bodyElement.parentNode() == contentElement, true);
1542 QCOMPARE(KoXml::childNodesCount(bodyElement), 1);
1543 QCOMPARE(bodyElement.firstChild().isNull(), false);
1544 QCOMPARE(bodyElement.lastChild().isNull(), false);
1545 QCOMPARE(bodyElement.previousSibling().isNull(), false);
1546 QCOMPARE(bodyElement.nextSibling().isNull(), true);
1547 QCOMPARE(bodyElement.localName(), QString("body"));
1548
1549 // also same <office:body>, but without namedItemNS
1550 KoXmlElement body2Element;
1551 body2Element = stylesElement.nextSibling().toElement();
1552 QCOMPARE(body2Element.isNull(), false);
1553 QCOMPARE(body2Element.isElement(), true);
1554 QCOMPARE(body2Element.parentNode().isNull(), false);
1555 QCOMPARE(body2Element.parentNode() == contentElement, true);
1556 QCOMPARE(KoXml::childNodesCount(body2Element), 1);
1557 QCOMPARE(body2Element.firstChild().isNull(), false);
1558 QCOMPARE(body2Element.lastChild().isNull(), false);
1559 QCOMPARE(body2Element.previousSibling().isNull(), false);
1560 QCOMPARE(body2Element.nextSibling().isNull(), true);
1561 QCOMPARE(body2Element.localName(), QString("body"));
1562
1563 // <office:text>
1564 KoXmlElement textElement;
1565 textElement = KoXml::namedItemNS(bodyElement, officeNS, "text");
1566 QCOMPARE(textElement.isNull(), false);
1567 QCOMPARE(textElement.isElement(), true);
1568 QCOMPARE(textElement.parentNode().isNull(), false);
1569 QCOMPARE(textElement.parentNode() == bodyElement, true);
1570 QCOMPARE(KoXml::childNodesCount(textElement), 1);
1571 QCOMPARE(textElement.firstChild().isNull(), false);
1572 QCOMPARE(textElement.lastChild().isNull(), false);
1573 QCOMPARE(textElement.previousSibling().isNull(), true);
1574 QCOMPARE(textElement.nextSibling().isNull(), true);
1575 QCOMPARE(textElement.localName(), QString("text"));
1576
1577 // the same <office:text>, but without namedItemNS
1578 KoXmlElement text2Element;
1579 text2Element = bodyElement.firstChild().toElement();
1580 QCOMPARE(text2Element.isNull(), false);
1581 QCOMPARE(text2Element.isElement(), true);
1582 QCOMPARE(text2Element.parentNode().isNull(), false);
1583 QCOMPARE(text2Element.parentNode() == bodyElement, true);
1584 QCOMPARE(KoXml::childNodesCount(text2Element), 1);
1585 QCOMPARE(text2Element.firstChild().isNull(), false);
1586 QCOMPARE(text2Element.lastChild().isNull(), false);
1587 QCOMPARE(text2Element.previousSibling().isNull(), true);
1588 QCOMPARE(text2Element.nextSibling().isNull(), true);
1589 QCOMPARE(text2Element.localName(), QString("text"));
1590
1591 // <text:p>
1592 KoXmlElement parElement;
1593 parElement = textElement.firstChild().toElement();
1594 QCOMPARE(parElement.isNull(), false);
1595 QCOMPARE(parElement.isElement(), true);
1596 QCOMPARE(parElement.parentNode().isNull(), false);
1597 QCOMPARE(parElement.parentNode() == textElement, true);
1598 QCOMPARE(KoXml::childNodesCount(parElement), 1);
1599 QCOMPARE(parElement.firstChild().isNull(), false);
1600 QCOMPARE(parElement.lastChild().isNull(), false);
1601 QCOMPARE(parElement.previousSibling().isNull(), true);
1602 QCOMPARE(parElement.nextSibling().isNull(), true);
1603 QCOMPARE(parElement.tagName(), QString("p"));
1604 QCOMPARE(parElement.text(), QString("Hello, world!"));
1605 QCOMPARE(parElement.attributeNS(QString(textNS), "style-name", ""), QString("Standard"));
1606 }
1607
testWhitespace()1608 void TestXmlReaderWithoutSpaces::testWhitespace()
1609 {
1610 QString errorMsg;
1611 int errorLine = 0;
1612 int errorColumn = 0;
1613
1614 QBuffer xmldevice;
1615 xmldevice.open(QIODevice::WriteOnly);
1616 QTextStream xmlstream(&xmldevice);
1617
1618 // content.xml for testing paragraphs with whitespace
1619 /* The list of elements for which whitespace should be preserved can be
1620 obtained from the Relax NG schema with these commands:
1621
1622 cat OpenDocument-schema-v1.0-os.rng| xmlstarlet sel \
1623 -N s="http://relaxng.org/ns/structure/1.0" -t -m '//s:text' \
1624 -v '../@name' -n |grep :
1625 cat OpenDocument-schema-v1.0-os.rng| xmlstarlet sel \
1626 -N s="http://relaxng.org/ns/structure/1.0" \
1627 -t -m "//s:ref[@name='paragraph-content']" -v '../../@name' -n |grep :
1628 */
1629
1630 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1631 xmlstream << "<office:document-content ";
1632 xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"";
1633 xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\">";
1634 xmlstream << "<text:p> </text:p>";
1635 xmlstream << "<text:p> <text:span/> </text:p>";
1636 xmlstream << "</office:document-content>";
1637 xmldevice.close();
1638
1639 KoXmlDocument doc(false);
1640 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
1641 QCOMPARE(errorMsg.isEmpty(), true);
1642 QCOMPARE(errorLine, 0);
1643 QCOMPARE(errorColumn, 0);
1644
1645 KoXmlElement p1;
1646 p1 = doc.documentElement().firstChild().toElement();
1647 QCOMPARE(p1.isNull(), false);
1648 QCOMPARE(p1.isElement(), true);
1649 QCOMPARE(KoXml::childNodesCount(p1), 1);
1650
1651 KoXmlElement p2;
1652 p2 = p1.nextSibling().toElement();
1653 QCOMPARE(p2.isNull(), false);
1654 QCOMPARE(p2.isElement(), true);
1655 QCOMPARE(KoXml::childNodesCount(p2), 3);
1656 }
1657
testSimpleOpenDocumentSpreadsheet()1658 void TestXmlReaderWithoutSpaces::testSimpleOpenDocumentSpreadsheet()
1659 {
1660 QString errorMsg;
1661 int errorLine = 0;
1662 int errorColumn = 0;
1663
1664 QBuffer xmldevice;
1665 xmldevice.open(QIODevice::WriteOnly);
1666 QTextStream xmlstream(&xmldevice);
1667
1668 // content.xml from a simple OpenDocument spreadsheet
1669 // the document has three worksheets, the last two are empty.
1670 // on the first sheet, cell A1 contains the text "Hello, world".
1671 // automatic styles, font declarations and unnecessary namespaces are omitted.
1672
1673 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1674 xmlstream << "<office:document-content ";
1675 xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
1676 xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
1677 xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\">";
1678 xmlstream << "<office:body>";
1679 xmlstream << "<office:spreadsheet>";
1680 xmlstream << "<table:table table:name=\"Sheet1\" table:style-name=\"ta1\" table:print=\"false\">";
1681 xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
1682 xmlstream << "<table:table-row table:style-name=\"ro1\">";
1683 xmlstream << "<table:table-cell office:value-type=\"string\">";
1684 xmlstream << "<text:p>Hello, world</text:p>";
1685 xmlstream << "</table:table-cell>";
1686 xmlstream << "</table:table-row>";
1687 xmlstream << "</table:table>";
1688 xmlstream << "<table:table table:name=\"Sheet2\" table:style-name=\"ta1\" table:print=\"false\">";
1689 xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
1690 xmlstream << "<table:table-row table:style-name=\"ro1\">";
1691 xmlstream << "<table:table-cell/>";
1692 xmlstream << "</table:table-row>";
1693 xmlstream << "</table:table>";
1694 xmlstream << "<table:table table:name=\"Sheet3\" table:style-name=\"ta1\" table:print=\"false\">";
1695 xmlstream << "<table:table-column table:style-name=\"co1\" table:default-cell-style-name=\"Default\"/>";
1696 xmlstream << "<table:table-row table:style-name=\"ro1\">";
1697 xmlstream << "<table:table-cell/>";
1698 xmlstream << "</table:table-row>";
1699 xmlstream << "</table:table>";
1700 xmlstream << "</office:spreadsheet>";
1701 xmlstream << "</office:body>";
1702 xmlstream << "</office:document-content>";
1703 xmldevice.close();
1704
1705 KoXmlDocument doc(false);
1706 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
1707 QCOMPARE(errorMsg.isEmpty(), true);
1708 QCOMPARE(errorLine, 0);
1709 QCOMPARE(errorColumn, 0);
1710
1711 QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
1712 QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
1713
1714 // <office:document-content>
1715 KoXmlElement contentElement;
1716 contentElement = doc.documentElement();
1717 QCOMPARE(contentElement.isNull(), false);
1718 QCOMPARE(contentElement.isElement(), true);
1719 QCOMPARE(contentElement.parentNode().isNull(), false);
1720 QCOMPARE(contentElement.parentNode().toDocument() == doc, true);
1721 QCOMPARE(KoXml::childNodesCount(contentElement), 1);
1722 QCOMPARE(contentElement.firstChild().isNull(), false);
1723 QCOMPARE(contentElement.lastChild().isNull(), false);
1724 QCOMPARE(contentElement.previousSibling().isNull(), false);
1725 QCOMPARE(contentElement.nextSibling().isNull(), true);
1726 QCOMPARE(contentElement.localName(), QString("document-content"));
1727
1728 // <office:body>
1729 KoXmlElement bodyElement;
1730 bodyElement = contentElement.firstChild().toElement();
1731 QCOMPARE(bodyElement.isNull(), false);
1732 QCOMPARE(bodyElement.isElement(), true);
1733 QCOMPARE(bodyElement.parentNode().isNull(), false);
1734 QCOMPARE(bodyElement.parentNode() == contentElement, true);
1735 QCOMPARE(KoXml::childNodesCount(bodyElement), 1);
1736 QCOMPARE(bodyElement.firstChild().isNull(), false);
1737 QCOMPARE(bodyElement.lastChild().isNull(), false);
1738 QCOMPARE(bodyElement.previousSibling().isNull(), true);
1739 QCOMPARE(bodyElement.nextSibling().isNull(), true);
1740 QCOMPARE(bodyElement.localName(), QString("body"));
1741
1742 // <office:spreadsheet>
1743 KoXmlElement spreadsheetElement;
1744 spreadsheetElement = bodyElement.firstChild().toElement();
1745 QCOMPARE(spreadsheetElement.isNull(), false);
1746 QCOMPARE(spreadsheetElement.isElement(), true);
1747 QCOMPARE(spreadsheetElement.parentNode().isNull(), false);
1748 QCOMPARE(spreadsheetElement.parentNode() == bodyElement, true);
1749 QCOMPARE(KoXml::childNodesCount(spreadsheetElement), 3);
1750 QCOMPARE(spreadsheetElement.firstChild().isNull(), false);
1751 QCOMPARE(spreadsheetElement.lastChild().isNull(), false);
1752 QCOMPARE(spreadsheetElement.previousSibling().isNull(), true);
1753 QCOMPARE(spreadsheetElement.nextSibling().isNull(), true);
1754 QCOMPARE(spreadsheetElement.localName(), QString("spreadsheet"));
1755
1756 // <table:table> for Sheet1
1757 KoXmlElement sheet1Element;
1758 sheet1Element = spreadsheetElement.firstChild().toElement();
1759 QCOMPARE(sheet1Element.isNull(), false);
1760 QCOMPARE(sheet1Element.isElement(), true);
1761 QCOMPARE(sheet1Element.parentNode().isNull(), false);
1762 QCOMPARE(sheet1Element.parentNode() == spreadsheetElement, true);
1763 QCOMPARE(KoXml::childNodesCount(sheet1Element), 2);
1764 QCOMPARE(sheet1Element.firstChild().isNull(), false);
1765 QCOMPARE(sheet1Element.lastChild().isNull(), false);
1766 QCOMPARE(sheet1Element.previousSibling().isNull(), true);
1767 QCOMPARE(sheet1Element.nextSibling().isNull(), false);
1768 QCOMPARE(sheet1Element.tagName(), QString("table"));
1769 QCOMPARE(sheet1Element.hasAttributeNS(tableNS, "name"), true);
1770 QCOMPARE(sheet1Element.attributeNS(tableNS, "name", ""), QString("Sheet1"));
1771 QCOMPARE(sheet1Element.attributeNS(tableNS, "style-name", ""), QString("ta1"));
1772 QCOMPARE(sheet1Element.attributeNS(tableNS, "print", ""), QString("false"));
1773
1774 // KoXml::load( sheet1Element, 100 );
1775
1776 // <table:table-column>
1777 KoXmlElement columnElement;
1778 columnElement = sheet1Element.firstChild().toElement();
1779 QCOMPARE(columnElement.isNull(), false);
1780 QCOMPARE(columnElement.isElement(), true);
1781 QCOMPARE(columnElement.parentNode().isNull(), false);
1782 QCOMPARE(columnElement.parentNode() == sheet1Element, true);
1783 QCOMPARE(KoXml::childNodesCount(columnElement), 0);
1784 QCOMPARE(columnElement.firstChild().isNull(), true);
1785 QCOMPARE(columnElement.lastChild().isNull(), true);
1786 QCOMPARE(columnElement.previousSibling().isNull(), true);
1787 QCOMPARE(columnElement.nextSibling().isNull(), false);
1788 QCOMPARE(columnElement.tagName(), QString("table-column"));
1789 QCOMPARE(columnElement.attributeNS(tableNS, "style-name", ""), QString("co1"));
1790 QCOMPARE(columnElement.attributeNS(tableNS, "default-cell-style-name", ""), QString("Default"));
1791
1792 // <table:table-row>
1793 KoXmlElement rowElement;
1794 rowElement = columnElement.nextSibling().toElement();
1795 QCOMPARE(rowElement.isNull(), false);
1796 QCOMPARE(rowElement.isElement(), true);
1797 QCOMPARE(rowElement.parentNode().isNull(), false);
1798 QCOMPARE(rowElement.parentNode() == sheet1Element, true);
1799 QCOMPARE(KoXml::childNodesCount(rowElement), 1);
1800 QCOMPARE(rowElement.firstChild().isNull(), false);
1801 QCOMPARE(rowElement.lastChild().isNull(), false);
1802 QCOMPARE(rowElement.previousSibling().isNull(), false);
1803 QCOMPARE(rowElement.nextSibling().isNull(), true);
1804 QCOMPARE(rowElement.tagName(), QString("table-row"));
1805 QCOMPARE(rowElement.attributeNS(tableNS, "style-name", ""), QString("ro1"));
1806
1807 // <table:table-cell>
1808 KoXmlElement cellElement;
1809 cellElement = rowElement.firstChild().toElement();
1810 QCOMPARE(cellElement.isNull(), false);
1811 QCOMPARE(cellElement.isElement(), true);
1812 QCOMPARE(cellElement.parentNode().isNull(), false);
1813 QCOMPARE(cellElement.parentNode() == rowElement, true);
1814 QCOMPARE(KoXml::childNodesCount(cellElement), 1);
1815 QCOMPARE(cellElement.firstChild().isNull(), false);
1816 QCOMPARE(cellElement.lastChild().isNull(), false);
1817 QCOMPARE(cellElement.previousSibling().isNull(), true);
1818 QCOMPARE(cellElement.nextSibling().isNull(), true);
1819 QCOMPARE(cellElement.tagName(), QString("table-cell"));
1820 QCOMPARE(cellElement.attributeNS(officeNS, "value-type", ""), QString("string"));
1821
1822 // <text:p>
1823 KoXmlElement parElement;
1824 parElement = cellElement.firstChild().toElement();
1825 QCOMPARE(parElement.isNull(), false);
1826 QCOMPARE(parElement.isElement(), true);
1827 QCOMPARE(parElement.parentNode().isNull(), false);
1828 QCOMPARE(parElement.parentNode() == cellElement, true);
1829 QCOMPARE(KoXml::childNodesCount(parElement), 1);
1830 QCOMPARE(parElement.firstChild().isNull(), false);
1831 QCOMPARE(parElement.lastChild().isNull(), false);
1832 QCOMPARE(parElement.previousSibling().isNull(), true);
1833 QCOMPARE(parElement.nextSibling().isNull(), true);
1834 QCOMPARE(parElement.tagName(), QString("p"));
1835 QCOMPARE(parElement.text(), QString("Hello, world"));
1836
1837 // <table:table> for Sheet2
1838 KoXmlElement sheet2Element;
1839 sheet2Element = sheet1Element.nextSibling().toElement();
1840 QCOMPARE(sheet2Element.isNull(), false);
1841 QCOMPARE(sheet2Element.isElement(), true);
1842 QCOMPARE(sheet2Element.parentNode().isNull(), false);
1843 QCOMPARE(sheet2Element.parentNode() == spreadsheetElement, true);
1844 QCOMPARE(KoXml::childNodesCount(sheet2Element), 2);
1845 QCOMPARE(sheet2Element.firstChild().isNull(), false);
1846 QCOMPARE(sheet2Element.lastChild().isNull(), false);
1847 QCOMPARE(sheet2Element.previousSibling().isNull(), false);
1848 QCOMPARE(sheet2Element.nextSibling().isNull(), false);
1849 QCOMPARE(sheet2Element.tagName(), QString("table"));
1850
1851 // </table:table> for Sheet3
1852 KoXmlElement sheet3Element;
1853 sheet3Element = sheet2Element.nextSibling().toElement();
1854 QCOMPARE(sheet3Element.isNull(), false);
1855 QCOMPARE(sheet3Element.isElement(), true);
1856 QCOMPARE(sheet3Element.parentNode().isNull(), false);
1857 QCOMPARE(sheet3Element.parentNode() == spreadsheetElement, true);
1858 QCOMPARE(KoXml::childNodesCount(sheet3Element), 2);
1859 QCOMPARE(sheet3Element.firstChild().isNull(), false);
1860 QCOMPARE(sheet3Element.lastChild().isNull(), false);
1861 QCOMPARE(sheet3Element.previousSibling().isNull(), false);
1862 QCOMPARE(sheet3Element.nextSibling().isNull(), true);
1863 QCOMPARE(sheet3Element.tagName(), QString("table"));
1864 }
1865
testSimpleOpenDocumentPresentation()1866 void TestXmlReaderWithoutSpaces::testSimpleOpenDocumentPresentation()
1867 {
1868 QString errorMsg;
1869 int errorLine = 0;
1870 int errorColumn = 0;
1871
1872 QBuffer xmldevice;
1873 xmldevice.open(QIODevice::WriteOnly);
1874 QTextStream xmlstream(&xmldevice);
1875
1876 // content.xml from a simple OpenDocument presentation
1877 // styles, declarations and unnecessary namespaces are omitted
1878 // the first page is "Title" and has two text boxes
1879 // the second page is
1880
1881 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1882 xmlstream << "<office:document-content ";
1883 xmlstream << " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
1884 xmlstream << " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
1885 xmlstream << " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" ";
1886 xmlstream << " xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" ";
1887 xmlstream << " xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" ";
1888 xmlstream << " office:version=\"1.0\">";
1889 xmlstream << "<office:scripts/>";
1890 xmlstream << "<office:automatic-styles/>";
1891 xmlstream << "<office:body>";
1892 xmlstream << "<office:presentation>";
1893 xmlstream << "<draw:page draw:name=\"Title\" draw:style-name=\"dp1\" ";
1894 xmlstream << " draw:master-page-name=\"lyt-cool\" ";
1895 xmlstream << " presentation:presentation-page-layout-name=\"AL1T0\">";
1896 xmlstream << "<draw:frame presentation:style-name=\"pr1\" ";
1897 xmlstream << " draw:text-style-name=\"P2\" draw:layer=\"layout\" ";
1898 xmlstream << " svg:width=\"23.912cm\" svg:height=\"3.508cm\" ";
1899 xmlstream << " svg:x=\"2.058cm\" svg:y=\"1.543cm\" ";
1900 xmlstream << " presentation:class=\"title\" ";
1901 xmlstream << " presentation:user-transformed=\"true\">";
1902 xmlstream << "<draw:text-box>";
1903 xmlstream << "<text:p text:style-name=\"P1\">Foobar</text:p>";
1904 xmlstream << "</draw:text-box>";
1905 xmlstream << "</draw:frame>";
1906 xmlstream << "<draw:frame presentation:style-name=\"pr2\" ";
1907 xmlstream << " draw:text-style-name=\"P3\" draw:layer=\"layout\"";
1908 xmlstream << " svg:width=\"23.912cm\" svg:height=\"13.231cm\"";
1909 xmlstream << " svg:x=\"2.058cm\" svg:y=\"5.838cm\" ";
1910 xmlstream << " presentation:class=\"subtitle\">";
1911 xmlstream << "<draw:text-box>";
1912 xmlstream << "<text:p text:style-name=\"P3\">Foo</text:p>";
1913 xmlstream << "</draw:text-box>";
1914 xmlstream << "</draw:frame>";
1915 xmlstream << "<presentation:notes draw:style-name=\"dp2\">";
1916 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\"/>";
1917 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\">";
1918 xmlstream << "<draw:text-box/>";
1919 xmlstream << "</draw:frame>";
1920 xmlstream << "</presentation:notes>";
1921 xmlstream << "</draw:page>";
1922 xmlstream << "<presentation:settings presentation:stay-on-top=\"true\"/>";
1923 xmlstream << "</office:presentation>";
1924 xmlstream << "</office:body>";
1925 xmlstream << "</office:document-content>";
1926 xmldevice.close();
1927
1928 KoXmlDocument doc(false);
1929 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
1930 QCOMPARE(errorMsg.isEmpty(), true);
1931 QCOMPARE(errorLine, 0);
1932 QCOMPARE(errorColumn, 0);
1933
1934 const char* officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
1935 const char* drawNS = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";
1936 const char* textNS = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
1937 const char* presentationNS = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";
1938 const char* svgNS = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
1939
1940 // <office:document-content>
1941 KoXmlElement contentElement;
1942 contentElement = doc.documentElement();
1943 QCOMPARE(contentElement.isNull(), false);
1944
1945 QCOMPARE(contentElement.isElement(), true);
1946 QCOMPARE(contentElement.parentNode().isNull(), false);
1947 QCOMPARE(contentElement.parentNode().toDocument() == doc, true);
1948 QCOMPARE(KoXml::childNodesCount(contentElement), 3);
1949 QCOMPARE(contentElement.firstChild().isNull(), false);
1950 QCOMPARE(contentElement.lastChild().isNull(), false);
1951 QCOMPARE(contentElement.previousSibling().isNull(), false);
1952 QCOMPARE(contentElement.nextSibling().isNull(), true);
1953 QCOMPARE(contentElement.localName(), QString("document-content"));
1954 QCOMPARE(contentElement.hasAttributeNS(officeNS, "version"), true);
1955 QCOMPARE(contentElement.attributeNS(officeNS, "version", ""), QString("1.0"));
1956
1957 // <office:scripts>
1958 KoXmlElement scriptsElement;
1959 scriptsElement = KoXml::namedItemNS(contentElement, officeNS, "scripts");
1960 QCOMPARE(scriptsElement.isNull(), false);
1961 QCOMPARE(scriptsElement.isElement(), true);
1962 QCOMPARE(scriptsElement.parentNode().isNull(), false);
1963 QCOMPARE(scriptsElement.parentNode() == contentElement, true);
1964 QCOMPARE(KoXml::childNodesCount(scriptsElement), 0);
1965 QCOMPARE(scriptsElement.firstChild().isNull(), true);
1966 QCOMPARE(scriptsElement.lastChild().isNull(), true);
1967 QCOMPARE(scriptsElement.previousSibling().isNull(), true);
1968 QCOMPARE(scriptsElement.nextSibling().isNull(), false);
1969 QCOMPARE(scriptsElement.localName(), QString("scripts"));
1970
1971 // <office:automatic-styles>
1972 KoXmlElement stylesElement;
1973 stylesElement = KoXml::namedItemNS(contentElement, officeNS, "automatic-styles");
1974 QCOMPARE(stylesElement.isNull(), false);
1975 QCOMPARE(stylesElement.isElement(), true);
1976 QCOMPARE(stylesElement.parentNode().isNull(), false);
1977 QCOMPARE(stylesElement.parentNode() == contentElement, true);
1978 QCOMPARE(KoXml::childNodesCount(stylesElement), 0);
1979 QCOMPARE(stylesElement.firstChild().isNull(), true);
1980 QCOMPARE(stylesElement.lastChild().isNull(), true);
1981 QCOMPARE(stylesElement.previousSibling().isNull(), false);
1982 QCOMPARE(stylesElement.nextSibling().isNull(), false);
1983 QCOMPARE(stylesElement.localName(), QString("automatic-styles"));
1984
1985 // also same <office:automatic-styles>, but without namedItemNS
1986 KoXmlNode styles2Element;
1987 styles2Element = scriptsElement.nextSibling().toElement();
1988 QCOMPARE(styles2Element.isNull(), false);
1989 QCOMPARE(styles2Element.isElement(), true);
1990 QCOMPARE(styles2Element.parentNode().isNull(), false);
1991 QCOMPARE(styles2Element.parentNode() == contentElement, true);
1992 QCOMPARE(KoXml::childNodesCount(styles2Element), 0);
1993 QCOMPARE(styles2Element.firstChild().isNull(), true);
1994 QCOMPARE(styles2Element.lastChild().isNull(), true);
1995 QCOMPARE(styles2Element.previousSibling().isNull(), false);
1996 QCOMPARE(styles2Element.nextSibling().isNull(), false);
1997 QCOMPARE(styles2Element.localName(), QString("automatic-styles"));
1998
1999 // <office:body>
2000 KoXmlElement bodyElement;
2001 bodyElement = KoXml::namedItemNS(contentElement, officeNS, "body");
2002 QCOMPARE(bodyElement.isNull(), false);
2003 QCOMPARE(bodyElement.isElement(), true);
2004 QCOMPARE(bodyElement.parentNode().isNull(), false);
2005 QCOMPARE(bodyElement.parentNode() == contentElement, true);
2006 QCOMPARE(KoXml::childNodesCount(bodyElement), 1);
2007 QCOMPARE(bodyElement.firstChild().isNull(), false);
2008 QCOMPARE(bodyElement.lastChild().isNull(), false);
2009 QCOMPARE(bodyElement.previousSibling().isNull(), false);
2010 QCOMPARE(bodyElement.nextSibling().isNull(), true);
2011 QCOMPARE(bodyElement.localName(), QString("body"));
2012
2013 // also same <office:body>, but without namedItemNS
2014 KoXmlElement body2Element;
2015 body2Element = stylesElement.nextSibling().toElement();
2016 QCOMPARE(body2Element.isNull(), false);
2017 QCOMPARE(body2Element.isElement(), true);
2018 QCOMPARE(body2Element.parentNode().isNull(), false);
2019 QCOMPARE(body2Element.parentNode() == contentElement, true);
2020 QCOMPARE(KoXml::childNodesCount(body2Element), 1);
2021 QCOMPARE(body2Element.firstChild().isNull(), false);
2022 QCOMPARE(body2Element.lastChild().isNull(), false);
2023 QCOMPARE(body2Element.previousSibling().isNull(), false);
2024 QCOMPARE(body2Element.nextSibling().isNull(), true);
2025 QCOMPARE(body2Element.localName(), QString("body"));
2026
2027 // <office:presentation>
2028 KoXmlElement presentationElement;
2029 presentationElement = KoXml::namedItemNS(bodyElement, officeNS, "presentation");
2030 QCOMPARE(presentationElement.isNull(), false);
2031 QCOMPARE(presentationElement.isElement(), true);
2032 QCOMPARE(presentationElement.parentNode().isNull(), false);
2033 QCOMPARE(presentationElement.parentNode() == bodyElement, true);
2034 QCOMPARE(KoXml::childNodesCount(presentationElement), 2);
2035 QCOMPARE(presentationElement.firstChild().isNull(), false);
2036 QCOMPARE(presentationElement.lastChild().isNull(), false);
2037 QCOMPARE(presentationElement.previousSibling().isNull(), true);
2038 QCOMPARE(presentationElement.nextSibling().isNull(), true);
2039 QCOMPARE(presentationElement.localName(), QString("presentation"));
2040
2041 // the same <office:presentation>, but without namedItemNS
2042 KoXmlElement presentation2Element;
2043 presentation2Element = bodyElement.firstChild().toElement();
2044 QCOMPARE(presentation2Element.isNull(), false);
2045 QCOMPARE(presentation2Element.isElement(), true);
2046 QCOMPARE(presentation2Element.parentNode().isNull(), false);
2047 QCOMPARE(presentation2Element.parentNode() == bodyElement, true);
2048 QCOMPARE(KoXml::childNodesCount(presentation2Element), 2);
2049 QCOMPARE(presentation2Element.firstChild().isNull(), false);
2050 QCOMPARE(presentation2Element.lastChild().isNull(), false);
2051 QCOMPARE(presentation2Element.previousSibling().isNull(), true);
2052 QCOMPARE(presentation2Element.nextSibling().isNull(), true);
2053 QCOMPARE(presentation2Element.localName(), QString("presentation"));
2054
2055 // <draw:page> for "Title"
2056 KoXmlElement titlePageElement;
2057 titlePageElement = presentationElement.firstChild().toElement();
2058 QCOMPARE(titlePageElement.isNull(), false);
2059 QCOMPARE(titlePageElement.isElement(), true);
2060 QCOMPARE(titlePageElement.parentNode().isNull(), false);
2061 QCOMPARE(titlePageElement.parentNode() == presentationElement, true);
2062 QCOMPARE(KoXml::childNodesCount(titlePageElement), 3);
2063 QCOMPARE(titlePageElement.firstChild().isNull(), false);
2064 QCOMPARE(titlePageElement.lastChild().isNull(), false);
2065 QCOMPARE(titlePageElement.previousSibling().isNull(), true);
2066 QCOMPARE(titlePageElement.nextSibling().isNull(), false);
2067 QCOMPARE(titlePageElement.localName(), QString("page"));
2068 QCOMPARE(titlePageElement.attributeNS(drawNS, "name", ""), QString("Title"));
2069 QCOMPARE(titlePageElement.attributeNS(drawNS, "style-name", ""), QString("dp1"));
2070 QCOMPARE(titlePageElement.attributeNS(drawNS, "master-page-name", ""), QString("lyt-cool"));
2071 QCOMPARE(titlePageElement.attributeNS(presentationNS,
2072 "presentation-page-layout-name", ""), QString("AL1T0"));
2073
2074 // <draw:frame> for the title frame
2075 KoXmlElement titleFrameElement;
2076 titleFrameElement = titlePageElement.firstChild().toElement();
2077 QCOMPARE(titleFrameElement.isNull(), false);
2078 QCOMPARE(titleFrameElement.isElement(), true);
2079 QCOMPARE(titleFrameElement.parentNode().isNull(), false);
2080 QCOMPARE(titleFrameElement.parentNode() == titlePageElement, true);
2081 QCOMPARE(KoXml::childNodesCount(titleFrameElement), 1);
2082 QCOMPARE(titleFrameElement.firstChild().isNull(), false);
2083 QCOMPARE(titleFrameElement.lastChild().isNull(), false);
2084 QCOMPARE(titleFrameElement.previousSibling().isNull(), true);
2085 QCOMPARE(titleFrameElement.nextSibling().isNull(), false);
2086 QCOMPARE(titleFrameElement.localName(), QString("frame"));
2087 QCOMPARE(titleFrameElement.attributeNS(presentationNS, "style-name", ""), QString("pr1"));
2088 QCOMPARE(titleFrameElement.attributeNS(presentationNS, "class", ""), QString("title"));
2089 QCOMPARE(titleFrameElement.attributeNS(presentationNS, "user-transformed", ""), QString("true"));
2090 QCOMPARE(titleFrameElement.attributeNS(drawNS, "text-style-name", ""), QString("P2"));
2091 QCOMPARE(titleFrameElement.attributeNS(drawNS, "layer", ""), QString("layout"));
2092 QCOMPARE(titleFrameElement.attributeNS(svgNS, "width", ""), QString("23.912cm"));
2093 QCOMPARE(titleFrameElement.attributeNS(svgNS, "height", ""), QString("3.508cm"));
2094 QCOMPARE(titleFrameElement.attributeNS(svgNS, "x", ""), QString("2.058cm"));
2095 QCOMPARE(titleFrameElement.attributeNS(svgNS, "y", ""), QString("1.543cm"));
2096
2097 // <draw:text-box> of the title frame
2098 KoXmlElement titleBoxElement;
2099 titleBoxElement = titleFrameElement.firstChild().toElement();
2100 QCOMPARE(titleBoxElement.isNull(), false);
2101 QCOMPARE(titleBoxElement.isElement(), true);
2102 QCOMPARE(titleBoxElement.parentNode().isNull(), false);
2103 QCOMPARE(titleBoxElement.parentNode() == titleFrameElement, true);
2104 QCOMPARE(KoXml::childNodesCount(titleBoxElement), 1);
2105 QCOMPARE(titleBoxElement.firstChild().isNull(), false);
2106 QCOMPARE(titleBoxElement.lastChild().isNull(), false);
2107 QCOMPARE(titleBoxElement.previousSibling().isNull(), true);
2108 QCOMPARE(titleBoxElement.nextSibling().isNull(), true);
2109 QCOMPARE(titleBoxElement.localName(), QString("text-box"));
2110
2111 // <text:p> for the title text-box
2112 KoXmlElement titleParElement;
2113 titleParElement = titleBoxElement.firstChild().toElement();
2114 QCOMPARE(titleParElement.isNull(), false);
2115 QCOMPARE(titleParElement.isElement(), true);
2116 QCOMPARE(titleParElement.parentNode().isNull(), false);
2117 QCOMPARE(titleParElement.parentNode() == titleBoxElement, true);
2118 QCOMPARE(KoXml::childNodesCount(titleParElement), 1);
2119 QCOMPARE(titleParElement.firstChild().isNull(), false);
2120 QCOMPARE(titleParElement.lastChild().isNull(), false);
2121 QCOMPARE(titleParElement.previousSibling().isNull(), true);
2122 QCOMPARE(titleParElement.nextSibling().isNull(), true);
2123 QCOMPARE(titleParElement.localName(), QString("p"));
2124 QCOMPARE(titleParElement.attributeNS(textNS, "style-name", ""), QString("P1"));
2125 QCOMPARE(titleParElement.text(), QString("Foobar"));
2126
2127 // <draw:frame> for the subtitle frame
2128 KoXmlElement subtitleFrameElement;
2129 subtitleFrameElement = titleFrameElement.nextSibling().toElement();
2130 QCOMPARE(subtitleFrameElement.isNull(), false);
2131 QCOMPARE(subtitleFrameElement.isElement(), true);
2132 QCOMPARE(subtitleFrameElement.parentNode().isNull(), false);
2133 QCOMPARE(subtitleFrameElement.parentNode() == titlePageElement, true);
2134 QCOMPARE(KoXml::childNodesCount(subtitleFrameElement), 1);
2135 QCOMPARE(subtitleFrameElement.firstChild().isNull(), false);
2136 QCOMPARE(subtitleFrameElement.lastChild().isNull(), false);
2137 QCOMPARE(subtitleFrameElement.previousSibling().isNull(), false);
2138 QCOMPARE(subtitleFrameElement.nextSibling().isNull(), false);
2139 QCOMPARE(subtitleFrameElement.localName(), QString("frame"));
2140 QCOMPARE(subtitleFrameElement.attributeNS(presentationNS, "style-name", ""), QString("pr2"));
2141 QCOMPARE(subtitleFrameElement.attributeNS(presentationNS, "class", ""), QString("subtitle"));
2142 QCOMPARE(subtitleFrameElement.hasAttributeNS(presentationNS, "user-transformed"), false);
2143 QCOMPARE(subtitleFrameElement.attributeNS(drawNS, "text-style-name", ""), QString("P3"));
2144 QCOMPARE(subtitleFrameElement.attributeNS(drawNS, "layer", ""), QString("layout"));
2145 QCOMPARE(subtitleFrameElement.attributeNS(svgNS, "width", ""), QString("23.912cm"));
2146 QCOMPARE(subtitleFrameElement.attributeNS(svgNS, "height", ""), QString("13.231cm"));
2147 QCOMPARE(subtitleFrameElement.attributeNS(svgNS, "x", ""), QString("2.058cm"));
2148 QCOMPARE(subtitleFrameElement.attributeNS(svgNS, "y", ""), QString("5.838cm"));
2149
2150 // <draw:text-box> of the subtitle frame
2151 KoXmlElement subtitleBoxElement;
2152 subtitleBoxElement = subtitleFrameElement.firstChild().toElement();
2153 QCOMPARE(subtitleBoxElement.isNull(), false);
2154 QCOMPARE(subtitleBoxElement.isElement(), true);
2155 QCOMPARE(subtitleBoxElement.parentNode().isNull(), false);
2156 QCOMPARE(subtitleBoxElement.parentNode() == subtitleFrameElement, true);
2157 QCOMPARE(KoXml::childNodesCount(subtitleBoxElement), 1);
2158 QCOMPARE(subtitleBoxElement.firstChild().isNull(), false);
2159 QCOMPARE(subtitleBoxElement.lastChild().isNull(), false);
2160 QCOMPARE(subtitleBoxElement.previousSibling().isNull(), true);
2161 QCOMPARE(subtitleBoxElement.nextSibling().isNull(), true);
2162 QCOMPARE(subtitleBoxElement.localName(), QString("text-box"));
2163
2164 // <text:p> for the subtitle text-box
2165 KoXmlElement subtitleParElement;
2166 subtitleParElement = subtitleBoxElement.firstChild().toElement();
2167 QCOMPARE(subtitleParElement.isNull(), false);
2168 QCOMPARE(subtitleParElement.isElement(), true);
2169 QCOMPARE(subtitleParElement.parentNode().isNull(), false);
2170 QCOMPARE(subtitleParElement.parentNode() == subtitleBoxElement, true);
2171 QCOMPARE(KoXml::childNodesCount(subtitleParElement), 1);
2172 QCOMPARE(subtitleParElement.firstChild().isNull(), false);
2173 QCOMPARE(subtitleParElement.lastChild().isNull(), false);
2174 QCOMPARE(subtitleParElement.previousSibling().isNull(), true);
2175 QCOMPARE(subtitleParElement.nextSibling().isNull(), true);
2176 QCOMPARE(subtitleParElement.localName(), QString("p"));
2177 QCOMPARE(subtitleParElement.attributeNS(textNS, "style-name", ""), QString("P3"));
2178 QCOMPARE(subtitleParElement.text(), QString("Foo"));
2179 }
2180
testSimpleOpenDocumentFormula()2181 void TestXmlReaderWithoutSpaces::testSimpleOpenDocumentFormula()
2182 {
2183 QString errorMsg;
2184 int errorLine = 0;
2185 int errorColumn = 0;
2186
2187 QBuffer xmldevice;
2188 xmldevice.open(QIODevice::WriteOnly);
2189 QTextStream xmlstream(&xmldevice);
2190
2191 // content.xml from a simple OpenDocument formula
2192 // this is essentially MathML
2193 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
2194 xmlstream << "<!DOCTYPE math:math PUBLIC \"-//OpenOffice.org//DTD Modified W3C MathML 1.01//EN\" \"math.dtd\">";
2195 xmlstream << "<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">";
2196 xmlstream << "<math:semantics>";
2197 xmlstream << "<math:mrow>";
2198 xmlstream << "<math:mi>E</math:mi>";
2199 xmlstream << "<math:mo math:stretchy=\"false\">=</math:mo>";
2200 xmlstream << "<math:msup>";
2201 xmlstream << "<math:mi math:fontstyle=\"italic\">mc</math:mi>";
2202 xmlstream << "<math:mn>2</math:mn>";
2203 xmlstream << "</math:msup>";
2204 xmlstream << "</math:mrow>";
2205 xmlstream << "<math:annotation math:encoding=\"StarMath 5.0\">E = mc^2 </math:annotation>";
2206 xmlstream << "</math:semantics>";
2207 xmlstream << "</math:math>";
2208 xmldevice.close();
2209
2210 KoXmlDocument doc(false);
2211 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
2212 QCOMPARE(errorMsg.isEmpty(), true);
2213 QCOMPARE(errorLine, 0);
2214 QCOMPARE(errorColumn, 0);
2215
2216 const char* mathNS = "http://www.w3.org/1998/Math/MathML";
2217
2218 // <math:math>
2219 KoXmlElement mathElement;
2220 mathElement = doc.documentElement();
2221 QCOMPARE(mathElement.isNull(), false);
2222 QCOMPARE(mathElement.isElement(), true);
2223 QCOMPARE(mathElement.parentNode().isNull(), false);
2224 QCOMPARE(mathElement.parentNode().toDocument() == doc, true);
2225 QCOMPARE(mathElement.firstChild().isNull(), false);
2226 QCOMPARE(mathElement.lastChild().isNull(), false);
2227 QCOMPARE(mathElement.previousSibling().isNull(), false);
2228 QCOMPARE(mathElement.nextSibling().isNull(), true);
2229 QCOMPARE(mathElement.localName(), QString("math"));
2230
2231 // <math:semantics>
2232 KoXmlElement semanticsElement;
2233 semanticsElement = KoXml::namedItemNS(mathElement, mathNS, "semantics");
2234 QCOMPARE(semanticsElement.isNull(), false);
2235 QCOMPARE(semanticsElement.isElement(), true);
2236 QCOMPARE(semanticsElement.parentNode().isNull(), false);
2237 QCOMPARE(semanticsElement.parentNode().toElement() == mathElement, true);
2238 QCOMPARE(semanticsElement.firstChild().isNull(), false);
2239 QCOMPARE(semanticsElement.lastChild().isNull(), false);
2240 QCOMPARE(semanticsElement.previousSibling().isNull(), true);
2241 QCOMPARE(semanticsElement.nextSibling().isNull(), true);
2242 QCOMPARE(semanticsElement.localName(), QString("semantics"));
2243
2244 // the same <math:semantics> but without namedItemNS
2245 KoXmlElement semantics2Element;
2246 semantics2Element = mathElement.firstChild().toElement();
2247 QCOMPARE(semantics2Element.isNull(), false);
2248 QCOMPARE(semantics2Element.isElement(), true);
2249 QCOMPARE(semantics2Element.parentNode().isNull(), false);
2250 QCOMPARE(semantics2Element.parentNode().toElement() == mathElement, true);
2251 QCOMPARE(semantics2Element.firstChild().isNull(), false);
2252 QCOMPARE(semantics2Element.lastChild().isNull(), false);
2253 QCOMPARE(semantics2Element.previousSibling().isNull(), true);
2254 QCOMPARE(semantics2Element.nextSibling().isNull(), true);
2255 QCOMPARE(semantics2Element.localName(), QString("semantics"));
2256
2257 // <math:mrow>
2258 KoXmlElement mrowElement;
2259 mrowElement = semanticsElement.firstChild().toElement();
2260 QCOMPARE(mrowElement.isNull(), false);
2261 QCOMPARE(mrowElement.isElement(), true);
2262 QCOMPARE(mrowElement.parentNode().isNull(), false);
2263 QCOMPARE(mrowElement.parentNode().toElement() == semanticsElement, true);
2264 QCOMPARE(mrowElement.firstChild().isNull(), false);
2265 QCOMPARE(mrowElement.lastChild().isNull(), false);
2266 QCOMPARE(mrowElement.previousSibling().isNull(), true);
2267 QCOMPARE(mrowElement.nextSibling().isNull(), false);
2268 QCOMPARE(mrowElement.localName(), QString("mrow"));
2269
2270 // <math:mi> for "E"
2271 KoXmlElement miElement;
2272 miElement = mrowElement.firstChild().toElement();
2273 QCOMPARE(miElement.isNull(), false);
2274 QCOMPARE(miElement.isElement(), true);
2275 QCOMPARE(miElement.parentNode().isNull(), false);
2276 QCOMPARE(miElement.parentNode().toElement() == mrowElement, true);
2277 QCOMPARE(miElement.firstChild().isNull(), false);
2278 QCOMPARE(miElement.lastChild().isNull(), false);
2279 QCOMPARE(miElement.previousSibling().isNull(), true);
2280 QCOMPARE(miElement.nextSibling().isNull(), false);
2281 QCOMPARE(miElement.localName(), QString("mi"));
2282
2283 // <math:mo> for "="
2284 KoXmlElement moElement;
2285 moElement = miElement.nextSibling().toElement();
2286 QCOMPARE(moElement.isNull(), false);
2287 QCOMPARE(moElement.isElement(), true);
2288 QCOMPARE(moElement.parentNode().isNull(), false);
2289 QCOMPARE(moElement.parentNode().toElement() == mrowElement, true);
2290 QCOMPARE(moElement.firstChild().isNull(), false);
2291 QCOMPARE(moElement.lastChild().isNull(), false);
2292 QCOMPARE(moElement.previousSibling().isNull(), false);
2293 QCOMPARE(moElement.nextSibling().isNull(), false);
2294 QCOMPARE(moElement.localName(), QString("mo"));
2295 QCOMPARE(moElement.attributeNS(mathNS, "stretchy", ""), QString("false"));
2296
2297 // <math:msup> for "mc" and superscripted "2"
2298 KoXmlElement msupElement;
2299 msupElement = moElement.nextSibling().toElement();
2300 QCOMPARE(msupElement.isNull(), false);
2301 QCOMPARE(msupElement.isElement(), true);
2302 QCOMPARE(msupElement.parentNode().isNull(), false);
2303 QCOMPARE(msupElement.parentNode().toElement() == mrowElement, true);
2304 QCOMPARE(msupElement.firstChild().isNull(), false);
2305 QCOMPARE(msupElement.lastChild().isNull(), false);
2306 QCOMPARE(msupElement.previousSibling().isNull(), false);
2307 QCOMPARE(msupElement.nextSibling().isNull(), true);
2308 QCOMPARE(msupElement.localName(), QString("msup"));
2309
2310 // <math:mi> inside the <math:msup> for "mc"
2311 KoXmlElement mcElement;
2312 mcElement = msupElement.firstChild().toElement();
2313 QCOMPARE(mcElement.isNull(), false);
2314 QCOMPARE(mcElement.isElement(), true);
2315 QCOMPARE(mcElement.parentNode().isNull(), false);
2316 QCOMPARE(mcElement.parentNode().toElement() == msupElement, true);
2317 QCOMPARE(mcElement.firstChild().isNull(), false);
2318 QCOMPARE(mcElement.lastChild().isNull(), false);
2319 QCOMPARE(mcElement.previousSibling().isNull(), true);
2320 QCOMPARE(mcElement.nextSibling().isNull(), false);
2321 QCOMPARE(mcElement.localName(), QString("mi"));
2322 QCOMPARE(mcElement.text(), QString("mc"));
2323 QCOMPARE(mcElement.attributeNS(mathNS, "fontstyle", ""), QString("italic"));
2324
2325 // <math:mn> inside the <math:msup> for "2" (superscript)
2326 KoXmlElement mnElement;
2327 mnElement = mcElement.nextSibling().toElement();
2328 QCOMPARE(mnElement.isNull(), false);
2329 QCOMPARE(mnElement.isElement(), true);
2330 QCOMPARE(mnElement.parentNode().isNull(), false);
2331 QCOMPARE(mnElement.parentNode().toElement() == msupElement, true);
2332 QCOMPARE(mnElement.firstChild().isNull(), false);
2333 QCOMPARE(mnElement.lastChild().isNull(), false);
2334 QCOMPARE(mnElement.previousSibling().isNull(), false);
2335 QCOMPARE(mnElement.nextSibling().isNull(), true);
2336 QCOMPARE(mnElement.localName(), QString("mn"));
2337 QCOMPARE(mnElement.text(), QString("2"));
2338
2339 // <math:annotation>
2340 KoXmlElement annotationElement;
2341 annotationElement = semanticsElement.lastChild().toElement();
2342 QCOMPARE(annotationElement.isNull(), false);
2343 QCOMPARE(annotationElement.isElement(), true);
2344 QCOMPARE(annotationElement.parentNode().isNull(), false);
2345 QCOMPARE(annotationElement.parentNode().toElement() == semanticsElement, true);
2346 QCOMPARE(annotationElement.firstChild().isNull(), false);
2347 QCOMPARE(annotationElement.lastChild().isNull(), false);
2348 QCOMPARE(annotationElement.previousSibling().isNull(), false);
2349 QCOMPARE(annotationElement.nextSibling().isNull(), true);
2350 QCOMPARE(annotationElement.localName(), QString("annotation"));
2351 QCOMPARE(annotationElement.text(), QString("E = mc^2 "));
2352 QCOMPARE(annotationElement.attributeNS(mathNS, "encoding", ""), QString("StarMath 5.0"));
2353 }
2354
testLargeOpenDocumentSpreadsheet()2355 void TestXmlReaderWithoutSpaces::testLargeOpenDocumentSpreadsheet()
2356 {
2357 QString errorMsg;
2358 int errorLine = 0;
2359 int errorColumn = 0;
2360
2361 int sheetCount = 4;
2362 int rowCount = 200;
2363 int colCount = 200 / 16;
2364
2365 QBuffer xmldevice;
2366 xmldevice.open(QIODevice::WriteOnly);
2367 QTextStream xmlstream(&xmldevice);
2368
2369 // content.xml
2370 xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2371 xmlstream << "<office:document-content ";
2372 xmlstream << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" ";
2373 xmlstream << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" ";
2374 xmlstream << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" >";
2375 xmlstream << "<office:body>";
2376 xmlstream << "<office:spreadsheet>";
2377 for (int i = 0; i < sheetCount; i++) {
2378 QString sheetName = QString("Sheet%1").arg(i + 1);
2379 xmlstream << "<table:table table:name=\"" << sheetName;
2380 xmlstream << "\" table:print=\"false\">";
2381 for (int j = 0; j < rowCount; j++) {
2382 xmlstream << "<table:table-row>";
2383 for (int k = 0; k < colCount; k++) {
2384 xmlstream << "<table:table-cell office:value-type=\"string\">";
2385 xmlstream << "<text:p>Hello, world</text:p>";
2386 xmlstream << "</table:table-cell>";
2387 }
2388 xmlstream << "</table:table-row>";
2389 }
2390 xmlstream << "</table:table>";
2391 }
2392 xmlstream << "</office:spreadsheet>";
2393 xmlstream << "</office:body>";
2394 xmlstream << "</office:document-content>";
2395 xmldevice.close();
2396
2397 printf("Raw XML size: %lld KB\n", xmldevice.size() / 1024);
2398
2399
2400 QTime timer;
2401
2402 #if 0
2403 // just to test parsing speed with plain dumb handler
2404 QXmlStreamReader *reader = new QXmlStreamReader(xmldevice);
2405 reader->setNamespaceProcessing(true);
2406 timer.start();
2407 ParseError error = parseDocument(*reader, doc);
2408 printf("Large spreadsheet: QXmlStreamReader parsing time is %d ms\n", timer.elapsed());
2409 delete reader;
2410 xmldevice.seek(0);
2411 #endif
2412
2413 KoXmlDocument doc(false);
2414
2415 timer.start();
2416 QCOMPARE(doc.setContent(&xmldevice, true, &errorMsg, &errorLine, &errorColumn), true);
2417 QCOMPARE(errorMsg.isEmpty(), true);
2418 QCOMPARE(errorLine, 0);
2419 QCOMPARE(errorColumn, 0);
2420
2421 if (!errorMsg.isEmpty()) {
2422 qDebug("Error: %s", qPrintable(errorMsg));
2423 return;
2424 }
2425
2426 printf("Large spreadsheet: KoXmlDocument parsing time is %d ms\n", timer.elapsed());
2427
2428 // release memory taken by the XML document content
2429 //xmlstream.setDevice( 0 );
2430
2431 // namespaces that will be used
2432 QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
2433 QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
2434
2435 // <office:document-content>
2436 KoXmlElement contentElement;
2437 contentElement = doc.documentElement();
2438 QCOMPARE(contentElement.isNull(), false);
2439 QCOMPARE(contentElement.isElement(), true);
2440 QCOMPARE(contentElement.localName(), QString("document-content"));
2441
2442 // <office:body>
2443 KoXmlElement bodyElement;
2444 bodyElement = contentElement.firstChild().toElement();
2445 QCOMPARE(bodyElement.isNull(), false);
2446 QCOMPARE(bodyElement.isElement(), true);
2447 QCOMPARE(bodyElement.localName(), QString("body"));
2448
2449 // <office:spreadsheet>
2450 KoXmlElement spreadsheetElement;
2451 spreadsheetElement = bodyElement.firstChild().toElement();
2452 QCOMPARE(spreadsheetElement.isNull(), false);
2453 QCOMPARE(spreadsheetElement.isElement(), true);
2454 QCOMPARE(spreadsheetElement.localName(), QString("spreadsheet"));
2455
2456 // now we visit every sheet, every row, every cell
2457 timer.start();
2458 KoXmlElement tableElement;
2459 tableElement = spreadsheetElement.firstChild().toElement();
2460 for (int table = 0; table < sheetCount; table++) {
2461 QString tableName = QString("Sheet%1").arg(table + 1);
2462 QCOMPARE(tableElement.isNull(), false);
2463 QCOMPARE(tableElement.isElement(), true);
2464 QCOMPARE(tableElement.localName(), QString("table"));
2465 QCOMPARE(tableElement.hasAttributeNS(tableNS, "name"), true);
2466 QCOMPARE(tableElement.attributeNS(tableNS, "name", ""), tableName);
2467 QCOMPARE(tableElement.attributeNS(tableNS, "print", ""), QString("false"));
2468
2469 // load everything for this table
2470 //KoXml::load( tableElement, 99 );
2471
2472 QCOMPARE(tableElement.parentNode().isNull(), false);
2473 QCOMPARE(tableElement.parentNode() == spreadsheetElement, true);
2474 QCOMPARE(tableElement.firstChild().isNull(), false);
2475 QCOMPARE(tableElement.lastChild().isNull(), false);
2476
2477 KoXmlElement rowElement;
2478 rowElement = tableElement.firstChild().toElement();
2479 for (int row = 0; row < rowCount; row++) {
2480 QCOMPARE(rowElement.isNull(), false);
2481 QCOMPARE(rowElement.isElement(), true);
2482 QCOMPARE(rowElement.localName(), QString("table-row"));
2483 QCOMPARE(rowElement.parentNode().isNull(), false);
2484 QCOMPARE(rowElement.parentNode() == tableElement, true);
2485 QCOMPARE(rowElement.firstChild().isNull(), false);
2486 QCOMPARE(rowElement.lastChild().isNull(), false);
2487
2488 KoXmlElement cellElement;
2489 cellElement = rowElement.firstChild().toElement();
2490 for (int col = 0; col < colCount; col++) {
2491 QCOMPARE(cellElement.isNull(), false);
2492 QCOMPARE(cellElement.isElement(), true);
2493 QCOMPARE(cellElement.localName(), QString("table-cell"));
2494 QCOMPARE(cellElement.text(), QString("Hello, world"));
2495 QCOMPARE(cellElement.hasAttributeNS(officeNS, "value-type"), true);
2496 QCOMPARE(cellElement.attributeNS(officeNS, "value-type", ""), QString("string"));
2497 QCOMPARE(cellElement.parentNode().isNull(), false);
2498 QCOMPARE(cellElement.parentNode() == rowElement, true);
2499 QCOMPARE(cellElement.firstChild().isNull(), false);
2500 QCOMPARE(cellElement.lastChild().isNull(), false);
2501 cellElement = cellElement.nextSibling().toElement();
2502 }
2503
2504 //KoXml::unload( rowElement );
2505 rowElement = rowElement.nextSibling().toElement();
2506 }
2507
2508 KoXml::unload(tableElement);
2509 tableElement = tableElement.nextSibling().toElement();
2510 }
2511
2512 printf("Large spreadsheet: iterating time is %d ms\n", timer.elapsed());
2513 }
2514
testExternalOpenDocumentSpreadsheet(const QString & filename)2515 void TestXmlReaderWithoutSpaces::testExternalOpenDocumentSpreadsheet(const QString& filename)
2516 {
2517 QProcess unzip;
2518 QStringList arguments;
2519 arguments << "-o" << filename << "content.xml";
2520
2521 printf("Unzipping content.xml from %s...\n", qPrintable(filename));
2522
2523 unzip.start("unzip", arguments);
2524 if (!unzip.waitForStarted()) {
2525 printf("Error: can't invoke unzip. Check your PATH and installation!\n\n");
2526 return;
2527 }
2528
2529 if (!unzip.waitForFinished()) {
2530 printf("Error: unzip failed, can't continue!\n\n");
2531 return;
2532 }
2533
2534 printf("Procesing content.xml....\n");
2535
2536 QString errorMsg;
2537 int errorLine = 0;
2538 int errorColumn = 0;
2539
2540 QFile xmlfile("content.xml");
2541 if (!xmlfile.open(QFile::ReadOnly)) {
2542 printf("Can not open file '%s'\n", qPrintable(filename));
2543 return;
2544 }
2545
2546 printf("Test external file: %s %lld KB\n", qPrintable(filename), xmlfile.size() / 1024);
2547
2548 QTime timer;
2549 timer.start();
2550
2551 KoXmlDocument doc(false);
2552
2553 QCOMPARE(KoXml::setDocument(doc, &xmlfile, true, &errorMsg, &errorLine, &errorColumn), true);
2554 QCOMPARE(errorMsg.isEmpty(), true);
2555 QCOMPARE(errorLine, 0);
2556 QCOMPARE(errorColumn, 0);
2557
2558 printf("External spreadsheet: parsing time is %d ms\n", timer.elapsed());
2559
2560 // namespaces that will be used
2561 QString officeNS = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
2562 QString tableNS = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
2563
2564 // <office:document-content>
2565 KoXmlElement contentElement;
2566 contentElement = doc.documentElement();
2567 QCOMPARE(contentElement.isNull(), false);
2568 QCOMPARE(contentElement.isElement(), true);
2569 QCOMPARE(contentElement.localName(), QString("document-content"));
2570
2571 long totalCellCount = 0;
2572
2573 KoXmlElement bodyElement;
2574 forEachElement(bodyElement, contentElement) {
2575 // <office:body>
2576 if (bodyElement.localName() != QString("body"))
2577 continue;
2578
2579 // now we iterate inside the body
2580 timer.start();
2581
2582 // <office:spreadsheet>
2583 KoXmlElement spreadsheetElement;
2584 spreadsheetElement = bodyElement.firstChild().toElement();
2585 QCOMPARE(spreadsheetElement.isNull(), false);
2586 QCOMPARE(spreadsheetElement.isElement(), true);
2587 QCOMPARE(spreadsheetElement.localName(), QString("spreadsheet"));
2588
2589 // now we visit every sheet
2590 long tableCount = -1;
2591 KoXmlElement tableElement;
2592 tableElement = spreadsheetElement.firstChild().toElement();
2593 for (;;) {
2594 if (tableElement.isNull())
2595 break;
2596
2597 if (tableElement.localName() != QString("table")) {
2598 tableElement = tableElement.nextSibling().toElement();
2599 continue;
2600 }
2601
2602 QString tableName = tableElement.attributeNS(tableNS, "name", "");
2603 tableCount++;
2604
2605 printf(" sheet #%ld (%s): ", tableCount + 1, qPrintable(tableName));
2606
2607 // use to preload everything in this sheet, will slow it down!
2608 // KoXml::load( tableElement, 50 );
2609
2610 long rowCount = -1;
2611 long cellCount = -1;
2612
2613 KoXmlElement rowElement;
2614 rowElement = tableElement.firstChild().toElement();
2615 for (;;) {
2616 if (rowElement.isNull())
2617 break;
2618
2619 if (rowElement.localName() != QString("table-row")) {
2620 rowElement = rowElement.nextSibling().toElement();
2621 continue;
2622 }
2623
2624 rowCount++;
2625 KoXml::load(rowElement, 4);
2626
2627 QCOMPARE(rowElement.isElement(), true);
2628 QCOMPARE(rowElement.localName(), QString("table-row"));
2629 QCOMPARE(rowElement.parentNode().isNull(), false);
2630 QCOMPARE(rowElement.parentNode() == tableElement, true);
2631
2632 KoXmlElement cellElement;
2633 cellElement = rowElement.firstChild().toElement();
2634 for (; ;) {
2635 if (cellElement.isNull())
2636 break;
2637
2638 if (cellElement.localName() != QString("table-cell")) {
2639 cellElement = cellElement.nextSibling().toElement();
2640 continue;
2641 }
2642
2643 cellCount++;
2644
2645 QCOMPARE(cellElement.isNull(), false);
2646 QCOMPARE(cellElement.isElement(), true);
2647 QCOMPARE(cellElement.localName(), QString("table-cell"));
2648 QString text1 = cellElement.text();
2649 QString text2 = cellElement.text();
2650 QCOMPARE(text1, text2);
2651 QString type1 = cellElement.attributeNS(officeNS, "value-type", QString());
2652 QString type2 = cellElement.attributeNS(officeNS, "value-type", QString());
2653 QCOMPARE(type1, type2);
2654 QString style1 = cellElement.attributeNS(tableNS, "style-name", QString());
2655 QString style2 = cellElement.attributeNS(tableNS, "style-name", QString());
2656 QCOMPARE(style1, style2);
2657
2658 QCOMPARE(cellElement.parentNode().isNull(), false);
2659 QCOMPARE(cellElement.parentNode() == rowElement, true);
2660
2661 cellElement = cellElement.nextSibling().toElement();
2662 }
2663
2664
2665 // better not to unload, freeing memory takes time
2666 KoXml::unload(rowElement);
2667
2668 rowElement = rowElement.nextSibling().toElement();
2669 }
2670
2671 printf(" %ld rows, %ld cells\n", rowCount + 1, cellCount + 1);
2672 totalCellCount += (cellCount + 1);
2673
2674 // IMPORTANT: helps minimizing memory usage !!
2675 // we do not need that element anymore, so just throw it away
2676 KoXml::unload(tableElement);
2677
2678 tableElement = tableElement.nextSibling().toElement();
2679 }
2680
2681 KoXml::unload(spreadsheetElement);
2682 }
2683
2684 printf("Total number of cells: %ld\n", totalCellCount);
2685
2686 int elapsed = timer.elapsed();
2687 printf("External spreadsheet: iterating time is %d ms\n", elapsed);
2688 if (elapsed > 0)
2689 printf(" approx. %ld cells/second\n", totalCellCount*1000 / elapsed);
2690
2691 // uncomment to check the XML
2692 xmlfile.remove();
2693 }
2694
2695 QTEST_GUILESS_MAIN(TestXmlReaderWithoutSpaces)
2696 #include <TestXmlReaderWithoutSpaces.moc>
2697
2698