// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_xml/tests/acdk/xml/dom/acdk_xml_dom_LibXML_Test.cpp,v 1.17 2005/04/25 13:20:47 kommer Exp $
#include <acdk.h>
#include <acdk/lang/System.h>
#include <acdk/io/CharArrayReader.h>
#include <acdk/io/File.h>
#include <acdk/io/GlobFilenameFilter.h>
#include <acdk/io/MemWriter.h>
#include <acdk/io/MemReader.h>
#include <acdk/tools/aunit/TestRunner.h>
#include <acdk/xml/sax/XMLReader.h>
#include <acdk/xml/libxmldom/LibXMLDocumentBuilder.h>
#include <acdk/xml/libxmldom/LibXMLDocument.h>
#include <org/w3c/dom/NodeList.h>
#include <org/w3c/dom/DOMWriter.h>
#include <acdk/net/URL.h>
namespace tests {
namespace acdk {
namespace xml {
namespace sax {
BEGIN_DECLARE_TEST( LibXML_Test )
DECLARE_TEST( standard )
DECLARE_TEST( files )
DECLARE_TEST( invalideXml )
DECLARE_TEST( invalideValidatedXml )
DECLARE_TEST( singleFile )
DECLARE_TEST( selectNodes )
DECLARE_TEST( selectNodesTyped )
DECLARE_TEST( xpath )
DECLARE_TEST( xmlWriter )
DECLARE_TEST( buildDocument )
DECLARE_TEST( manipulateDocument )
DECLARE_TEST( createDocument )
DECLARE_TEST( createDocument2 )
DECLARE_TEST( copyBetweenDocuments )
DECLARE_TEST( parsePrintHtml )
DECLARE_TEST( memConsumingTest )
END_DECLARE_TEST( LibXML_Test )
BEGIN_DEFINE_TEST( LibXML_Test )
ADD_TEST( LibXML_Test, standard )
ADD_TEST( LibXML_Test, files )
ADD_TEST( LibXML_Test, invalideXml )
ADD_TEST( LibXML_Test, invalideValidatedXml )
ADD_TEST( LibXML_Test, singleFile )
ADD_TEST( LibXML_Test, selectNodes )
ADD_TEST( LibXML_Test, selectNodesTyped )
ADD_TEST( LibXML_Test, xpath )
ADD_TEST( LibXML_Test, xmlWriter )
ADD_TEST( LibXML_Test, buildDocument )
ADD_TEST( LibXML_Test, manipulateDocument )
ADD_TEST( LibXML_Test, createDocument )
ADD_TEST( LibXML_Test, createDocument2 )
ADD_TEST( LibXML_Test, copyBetweenDocuments )
ADD_TEST( LibXML_Test, parsePrintHtml )
ADD_TEST( LibXML_Test, memConsumingTest )
END_DEFINE_TEST( LibXML_Test )
using namespace ::org::w3c::dom;
using namespace ::org::xml::sax;
using namespace ::acdk::xml::libxmldom;
using namespace ::acdk::xml::sax;
void printDomNodes(IN(::acdk::io::RPrintWriter) out, IN(::org::w3c::dom::RNode) node, IN(RString) ident)
{
//RString textCont = node->getTextContent();
out->println(ident + acdk::lang::Object(node)->toString());
if (node->hasChildNodes() == false)
return;
::org::w3c::dom::RNodeList nl = node->getChildNodes();
int count = nl->getLength();
for (int i = 0; i < count; ++i)
{
printDomNodes(out, nl->item(i), ident + " ");
}
}
void
LibXML_Test::standard()
{
//System::in->readLine();
LibXMLDocumentBuilder parser;
const char* text =
"<?xml version=\"1.0\"?>"
"<book>"
"<title value=\"asdf\"/>"
"<content>"
"Text of Book"
"</content>"
"</book>"
""
;
RbyteArray ba = new byteArray((const byte*)text, strlen(text));
::acdk::io::MemReader memreader(ba);
::org::w3c::dom::RDocument doc = parser.parse((::acdk::io::RReader)&memreader);
//printDomNodes(System::out, &doc, "");
printDomNodes(System::out, &doc, "");
//RLibXMLDocument(doc)->releaseNode();
}
static RLibXMLDocument parseDocument(::acdk::io::File& f, int extendedParseFlags, IN(RErrorHandler) errorHandler = Nil)
{
//try {
LibXMLDocumentBuilder parser;
parser.setExtendedFlags(extendedParseFlags);
if (errorHandler != Nil)
parser.setErrorHandler(errorHandler);
::acdk::io::RReader in = f.getReader();
//::acdk::io::MemWriter bout;
//in->trans(&bout);
//RString text = f.getReader()->getCharReader()->readString();
RLibXMLDocument doc = (RLibXMLDocument)parser.parse(in, ::acdk::net::URL::fileAsUrlName(&f));
//System::out->println("Parsed: " + doc->toString() + "\n" + doc->toXml());
return doc;
//} catch (RThrowable ex) {
// System::out->println("Parsing file failed: " + f.getCanonicalPath() + ": " + ex->getMessage());
return Nil;
//}
return Nil;
}
static RLibXMLDocument parseDocument(IN(RString) fname, int extendedParseFlags = 0, bool printDom = false)
{
RString s = System::getAcdkHome() + "/acdk_xml/cfg/tests/acdk/xml/" + fname;
::acdk::io::File f(s);
RLibXMLDocument doc = parseDocument(f, extendedParseFlags);
if (printDom == true)
printDomNodes(System::out, &doc, "");
return doc;
}
void
LibXML_Test::files()
{
RString s = System::getAcdkHome() + "/acdk_xml/cfg/tests/acdk/xml";
::acdk::io::File dir(s);
RStringArray files = dir.list(new ::acdk::io::GlobFilenameFilter("*.xml"), ::acdk::io::FileListFiles);
bool testFailed = false;
for (int i = 0; i < files->length(); ++i)
{
::acdk::io::File f(&dir, files[i]);
try {
parseDocument(f, 0);
} catch (RSAXParseException ex) {
System::out->println("Test failed: " + f.getCanonicalPath() + ex->getMessage());
testFailed = true;
}
}
testAssertComment(testFailed == false, "One or more tests are failed");
}
void
LibXML_Test::invalideXml()
{
RString s = System::getAcdkHome() + "/acdk_xml/cfg/tests/acdk/xml/invalid";
::acdk::io::File dir(s);
RStringArray files = dir.list(new ::acdk::io::GlobFilenameFilter("*.xml"), ::acdk::io::FileListRecursive | ::acdk::io::FileListFiles);
bool testFailed = false;
for (int i = 0; i < files->length(); ++i)
{
::acdk::io::File f(&dir, files[i]);
try {
parseDocument(f, 0);
testFailed = true;
System::out->println("Test failed: " + f.getCanonicalPath());
} catch (RSAXParseException ex) {
System::out->println("Expected Exception: " + f.getCanonicalPath() + ex->getMessage());
}
}
testAssertComment(testFailed == false, "One or more tests are failed");
}
void
LibXML_Test::invalideValidatedXml()
{
RString s = System::getAcdkHome() + "/acdk_xml/cfg/tests/acdk/xml/validate/invalid";
::acdk::io::File dir(s);
RStringArray files = dir.list(new ::acdk::io::GlobFilenameFilter("*.xml"), ::acdk::io::FileListRecursive | ::acdk::io::FileListFiles);
bool testFailed = false;
for (int i = 0; i < files->length(); ++i)
{
::acdk::io::File f(&dir, files[i]);
try {
parseDocument(f, XMLRF_PARSE_DTDVALID | XMLRF_PARSE_NOENT);
testFailed = true;
System::out->println("Test failed: " + f.getCanonicalPath());
} catch (RSAXParseException ex) {
System::out->println("Expected Exception: " + f.getCanonicalPath() + ex->getMessage());
}
}
testAssertComment(testFailed == false, "One or more tests are failed");
}
void
LibXML_Test::singleFile()
{
System::out->println("This test is for development only");
//::acdk::xml::dom::RXMLDocument doc = parseDocument("02_PcData.xml");
//::acdk::xml::dom::RXMLDocument docp = new ::acdk::xml::dom::XMLDocument();
//docp->setDocumentRoot(new XMLElement("sadf"));
{
//::acdk::xml::dom::RXMLDocument doc = parseDocument("80_NsTest.xml");
}
{
/*
//RLibXMLDocument doc = parseDocument("validate/invalid/01_web_local.xml");
::acdk::io::File f("C:\\d\\artefaktur\\acdk_doc\\docs\\wxWidgets\\html\\wx\\wx_wxcolour.html");
RLibXMLDocument doc = parseDocument(f, ::acdk::xml::sax::XMLRF_PARSE_HTML_FLAGS | HTML_PARSE_NOERROR, Nil);
//printDomNodes(System::out, &doc, "");
System::out->println("AS HTML:\n");
doc->write(System::out->getWriter());
System::out->println("\n\n\nAS XML:\n");
doc->write(System::out->getWriter(), NWFWithIndent | NWFWHtmlAsXml);
*/
/*
doc->selectNode("/book/body/text()");
RString v = doc->selectNode("/book/body/text()")->getNodeValue();
{
RString v2 = doc->selectNode("/book")->selectNode("body/text()")->getNodeValue();
testAssert(v->equals(v2) == true);
}
System::out->println(v);
doc = parseDocument("60_Utf8Encoding.xml");
RString v2 = doc->selectNode("/book/body/text()")->getNodeValue();
RString v1i = v->convert(CCUtf8);
RString v2i = v2->convert(CCUtf8);
System::out->println(v);
testAssert(v->equals(v2) == true);
*/
}
}
void
LibXML_Test::selectNodes()
{
RLibXMLDocument doc = parseDocument("validate/01_web_local.xml");
RNode n = doc->selectNode("/web-app/display-name");
testAssert(n != Nil);
n = n->selectNode("text()");
testAssert(n->getNodeValue()->equals("sampleapp.war") == true);
n = doc->selectNode("/web-app/servlet");
doc = Nil;
RNodeList nl = n->selectNodes("init-param");
testAssert(nl != Nil && nl->getLength() > 0);
RNode ne;
::acdk::util::RIterator it = nl->iterator();
while (it->hasNext() == true)
{
ne = (RNode)it->next();
System::out->println("Node: " + ne->getNodeName());
}
}
void
LibXML_Test::selectNodesTyped()
{
RLibXMLDocument doc = parseDocument("10_SelectTyped.xml");
RString docAsXML = doc->toXML();
acdk::lang::Object o;
RString s;
RNumber n;
RBoolean b;
o = doc->selectObject("/entries/entry");
testAssert(instanceof(o, NodeList) == true);
o = doc->selectObject("/entries/entry[1]");
testAssert(instanceof(o, Node) == true);
// xpath casting functions string(), number(), and boolean().
// select path and cast it to string
o = doc->selectObject("string(/entries/entry[@type=\"stringval\"]/text())");
testAssert(instanceof(o, String) == true);
s = (RString)o;
testAssert(s->equals("asdf") == true);
// select path and cast it to number
o = doc->selectObject("number(/entries/entry[@type=\"intval\"]/text())");
testAssert(instanceof(o, Number) == true);
n = (RNumber)o;
testAssert(n->intValue() == 12345);
// select path and cast it to boolean
o = doc->selectObject("boolean(/entries/entry[@type=\"boolval\"]/text())");
testAssert(instanceof(o, Boolean) == true);
b = (RBoolean)o;
testAssert(b->booleanValue() == true);
}
void
LibXML_Test::xpath()
{
RLibXMLDocument doc = parseDocument("xpath/40_XPathExpr.xml");
RNode node = doc->selectNode("/book/title");
testAssert(node != Nil);
node = doc->selectNode("/book/title[@value=\"This is another Title\"]");
testAssert(node != Nil);
node = doc->selectNode("/book/body/chapter[@num=\"2\"]");
/* does not work testAssert(node != Nil);
node = node->selectNode("par[text()=\"Second Text 2\"]");
*/
/* todo
/element/@* selects all attributes
/element/text() selects the text inside element
*/
}
void
LibXML_Test::xmlWriter()
{
RLibXMLDocument doc = parseDocument("validate/01_web_local.xml");
::acdk::io::MemWriter mout;
DOMWriter writer(&mout, DOMWriterFormat::createPretty());
writer.writeDocument(&doc);
System::out->getWriter()->write(mout.getBuffer());
System::out->println();
}
void
LibXML_Test::buildDocument()
{
LibXMLDocumentBuilder docBuilder;
RDocument doc = docBuilder.newDocument();
RElement el = doc->addElement("rootNode")->addElement("childNode");
for (int i = 0; i < 4; ++i)
{
el->addComment("This is comment");
el->addElement("listel");
el->addText("BlaBla");
//el->
}
::acdk::io::MemWriter mout;
DOMWriter writer(&mout, DOMWriterFormat::createPretty());
writer.writeDocument(&doc);
System::out->getWriter()->write(mout.getBuffer());
System::out->println();
}
void
LibXML_Test::manipulateDocument()
{
RLibXMLDocument doc = parseDocument("validate/01_web_local.xml");
RNode el = doc->selectNode("/web-app/servlet[1]");
RNode removedEl = el->detach();
removedEl = Nil;
}
void
LibXML_Test::createDocument()
{
LibXMLDocumentBuilder docBuilder;
RDocument document = docBuilder.newDocument();
//RDocument document = new LibXMLDocument("Root");
org::w3c::dom::RElement parent = document->createElement("Parent");
org::w3c::dom::RElement first = document->createElement("FirstChild");
org::w3c::dom::RElement second = document->createElement("SecondChild");
org::w3c::dom::RElement third = document->createElement("ThirdChild");
document->appendChild(&parent);
parent->appendChild(&first);
parent->appendChild(&second);
parent->appendChild(&third);
org::w3c::dom::RElement newFirst = document->createElement("NewFirst");
org::w3c::dom::RElement oldFirst = (org::w3c::dom::RElement) parent->replaceChild(&newFirst, &first);
// check the return value of replaceChild
testAssert(oldFirst->isEqualNode(&first) == true);
/// make sure the old node has been replaced
RNodeList children = parent->getChildNodes();
RNode firstChild = children->item(0);
testAssert(ELEMENT_NODE == firstChild->getNodeType());
testAssert(newFirst->isEqualNode(&firstChild) == true);
RString xmlstr = document->toXML();
System::out->println("Created Document: " + xmlstr);
// try to replace a node that doesn't exist
org::w3c::dom::RElement badNode = document->createElement("NoChild");
try {
parent->replaceChild(&newFirst, &badNode);
testAssertComment(false, "DOMException should be throwed when trying to replace non existing child");
} catch (RDOMException e) {
testAssert(NOT_FOUND_ERR == e->getCode());
}
}
void
LibXML_Test::createDocument2()
{
// sample from dom4j
RDocument document = LibXMLDocumentBuilder().newDocument();
RElement root = document->addElement("root");
RElement author1 = root->addElement( "author" )
->addAttribute( "name", "James" )
->addAttribute( "location", "UK" )
->addText( "James Strachan" );
RElement author2 = root->addElement( "author" )
->addAttribute( "name", "Bob" )
->addAttribute( "location", "US" )
->addText( "Bob McWhirter" );
RString xmlstr = document->toXML();
System::out->println("Created Document: " + xmlstr);
}
void
LibXML_Test::copyBetweenDocuments()
{
RLibXMLDocument book1 = parseDocument("03_Book1.xml");
RLibXMLDocument book2 = parseDocument("03_Book2.xml");
RNodeList nodes = book1->selectNodes("/book/chapter");
RNode inspos = book2->selectNode("/book");
for (int i = 0; i < nodes->getLength(); ++i)
{
RLibXMLNode cloned = (RLibXMLNode)nodes->item(i)->cloneNode(true);
RElement(inspos)->appendChild(&cloned);
}
nodes = Nil;
book1 = Nil;
book2->write(System::out->getWriter(), NWFWithIndent);
}
void
LibXML_Test::parsePrintHtml()
{
LibXMLDocumentBuilder parser;
parser.setExtendedFlags(::acdk::xml::sax::XMLRF_PARSE_HTML_FLAGS);
// read from file
{
RString extTempFile = System::getAcdkHome() + "/index.html";
::acdk::io::File f(extTempFile);
if (f.exists() == false)
{
// skip test
return;
}
RLibXMLDocument doc = (RLibXMLDocument)parser.parse(f.getReader(), f.getCanonicalPath());
doc->write(System::out->getWriter(), NWFWithIndent, 0, "HTML");
}
// read from memory
{
char* htmlFragment =
"<html><body><h2> </h2></body></html>";
RbyteArray ba = new byteArray((const byte*)htmlFragment, strlen(htmlFragment));
::acdk::io::MemReader memreader(ba);
RLibXMLDocument doc = (RLibXMLDocument)parser.parse(&memreader, "");
doc->write(System::out->getWriter(), NWFWithIndent, 0, "HTML");
System::out->println("");
}
}
void parseXmlFile(IN(::acdk::io::RFile) f)
{
System::out->println("parse file: " + f->getName());
LibXMLDocumentBuilder parser;
RLibXMLDocument doc = (RLibXMLDocument)parser.parse(f->getReader(), f->getCanonicalPath());
}
void
LibXML_Test::memConsumingTest()
{
RString inputPath = "C:\\d\\artefaktur\\extsrc\\unicode_locals";
::acdk::io::RFile dir = new ::acdk::io::File(inputPath);
if (dir->exists() == false)
return;
RStringArray files = dir->list();
for (int i = 0; i < files->length(); ++i)
{
RString fn = files[i];
if (fn->endsWith(".xml") == false)
continue;
if (fn->startsWith("ar") == false)
continue;
::acdk::io::RFile xmlFile = new ::acdk::io::File(dir, fn);
parseXmlFile(xmlFile);
}
}
} // namespace sax
} // namespace xml
} // namespace acdk
} // namespace tests
|