From: Arjen Baart Date: Sun, 9 Feb 2020 15:27:20 +0000 (+0100) Subject: Add class xml X-Git-Tag: V0.3 X-Git-Url: http://www.andromeda.nl/gitweb/?a=commitdiff_plain;h=b808094e5a766f48e9e2289c7a0887132a9882ef;p=libacl.git Add class xml --- diff --git a/ChangeLog b/ChangeLog index fb8153d..b959431 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,13 @@ +Feb 07, 2020 - Release 0.3 +============================ + - hour: Add and subtract a number of seconds. - Add parameter bool localtime to now() and today() - String: Boundary checking on index and subtring operators - Ported class Integer from the Gnu libg++ library. - Added date::Weekday() - Added class configration + - Added class xml Oct 31, 2019 - Release 0.2 ============================ diff --git a/configure.ac b/configure.ac index 19c4c15..302db0b 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([libACL], [0.2], [arjen@androemda.nl]) +AC_INIT([libACL], [0.3], [arjen@androemda.nl]) AC_CONFIG_SRCDIR([src/date.cpp]) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIRS([m4]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 76537f1..e863ea0 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -38,7 +38,7 @@ manual.txt : $(XMLS) xml2text manual.xml > manual.txt check: - xmllint --noout --xinclude --loaddtd --noent --schema ../doc.xsd manual.xml +# xmllint --noout --xinclude --loaddtd --noent --schema /usr/local/xslt/doc.xsd manual.xml # xmllint --noout --valid $(XMLS) clean-local: diff --git a/src/Makefile.am b/src/Makefile.am index a52770b..19b99dd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,8 +3,9 @@ lib_LTLIBRARIES = libACL.la libACL_la_SOURCES = string.cpp regex.cpp date.cpp parsedate.c dateyacc.y datelex.c \ hour.cpp utc.cpp \ Integer.cpp \ + xml.cpp \ configuration.cpp -libACL_la_LDFLAGS = -version-info 2:2:0 +libACL_la_LDFLAGS = -version-info 0:3:0 -include_HEADERS = String.h date.h Integer.h configuration.h +include_HEADERS = String.h date.h Integer.h xml.h configuration.h diff --git a/src/utc.cpp b/src/utc.cpp index 3a5548f..934ba38 100644 --- a/src/utc.cpp +++ b/src/utc.cpp @@ -36,8 +36,6 @@ *****************************/ -static const char *RCSID = "$Id: utc.cpp,v 1.1 2002-09-28 06:58:45 arjen Exp $"; - #include #include "date.h" diff --git a/src/xml.cpp b/src/xml.cpp new file mode 100644 index 0000000..2ec74c7 --- /dev/null +++ b/src/xml.cpp @@ -0,0 +1,44 @@ + +#include "xml.h" + +String xml::RootElementName(void) +{ + String root_name; + xmlNodePtr root; + + root = xmlDocGetRootElement(document); + root_name = String((const char *)root->name); + + return root_name; +} + +xml_node xml::RootNode(void) +{ + xmlNodePtr root; + + root = xmlDocGetRootElement(document); + + return xml_node(root); +} + +// Find the nth child element by name (non-recursive) +xml_node xml_node::FindChildElement(String name, int nth) +{ + xml_node element; + xmlNodePtr node = n->children; + + while (element.n == NULL && node != NULL) + { + if (node->type == XML_ELEMENT_NODE && name == (const char *)node->name) + { + if (nth == 0) + { + element.n = node; + } + nth--; + } + node = node->next; + } + + return element; +} diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..63f1e5a --- /dev/null +++ b/src/xml.h @@ -0,0 +1,90 @@ +#include // usually in /usr/include/libxml2, see xml2-config + +#include "String.h" + +class xml_node +{ + xmlNodePtr n; + +public: + + xml_node() + { + n = NULL; + } + + xml_node(xmlNodePtr np) + { + n = np; + } + + bool is_a_node(void) + { + return n != NULL; + } + + String name(void) + { + String node_name; + + if (n != NULL) + { + node_name = String((const char *)n->name); + } + + return node_name; + } + + // Assumes one childnode of type TEXT + // TODO collect content from multiple TEXT nodes (recursively ?) + String content(void) + { + String node_content; + + if (n != NULL) + { + node_content = String((const char *)n->children->content); + } + + return node_content; + } + + // Find the nth child element by name (non-recursive) + xml_node FindChildElement(String name, int nth = 0); +}; + +class xml +{ + xmlDocPtr document; + +public: + + xml() + { + document = NULL; + } + + ~xml() + { + if (document != NULL) + { + xmlFreeDoc(document); + document = NULL; + } + } + + void ParseFile(const char * filename) + { + document = xmlParseFile(filename); + } + + void SaveFile(const char * filename) + { + xmlSaveFile(filename, document); + } + + String RootElementName(void); + xml_node RootNode(void); + +}; + diff --git a/test/Makefile.am b/test/Makefile.am index cb977a1..740bac0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,6 +7,7 @@ check_PROGRAMS = string_assign string_basics string_compare string_cat string_su hour_assign hour_parse hour_compare hour_arithmetic hour_check_now \ utc_assign utc_compare utc_arithmetic \ integer_assign integer_factorial integer_fibonacci integer_pow64 integer_modulo \ + xml_file xml_find \ configuration_read configuration_find string_assign_SOURCES = string_assign.cpp @@ -43,5 +44,8 @@ integer_fibonacci_SOURCES = integer_fibonacci.cpp tInteger.cpp integer_pow64_SOURCES = integer_pow64.cpp tInteger.cpp integer_modulo_SOURCES = integer_modulo.cpp tInteger.cpp +xml_file_SOURCES = xml_file.cpp +xml_find_SOURCES = xml_find.cpp + configuration_read_SOURCES = configuration_read.cpp configuration_find_SOURCES = configuration_find.cpp diff --git a/test/xml_file.cpp b/test/xml_file.cpp new file mode 100644 index 0000000..ea4722e --- /dev/null +++ b/test/xml_file.cpp @@ -0,0 +1,29 @@ +/******************************************************* + * Unit test for the xml class + * + * test reading and writing of xml files. + ****************************************************** + * + */ + +#include "xml.h" +#include + +int main() +{ + xml doc; + String root; + xml_node root_node; + + doc.ParseFile("xml_test01.xml"); + doc.SaveFile("xml_test01.out.xml"); + + root = doc.RootElementName(); + assert (root == "doc"); + + root_node = doc.RootNode(); + assert(root_node.name() == "doc"); + + return 0; +} + diff --git a/test/xml_find.cpp b/test/xml_find.cpp new file mode 100644 index 0000000..b5c3cd6 --- /dev/null +++ b/test/xml_find.cpp @@ -0,0 +1,85 @@ +/******************************************************* + * Unit test for the xml class + * + * test finding content in xml nodes + ****************************************************** + * + */ + +#include "xml.h" +#include + +int main() +{ + xml doc; + xml_node root_node; + xml_node found_node; + String child_name; + String title_content; + + const char xml_file[] = "xml_test01.xml"; + + std::cout << "Reading XML file " << xml_file << "\n"; + + doc.ParseFile("xml_test01.xml"); + + root_node = doc.RootNode(); + + std::cout << "Root element is " << root_node.name() << "\n"; + assert(root_node.name() == "doc"); + + child_name = "book"; + found_node = root_node.FindChildElement(child_name); + std::cout << "Child element " << child_name; + if (!found_node.is_a_node()) + { + std::cout << " not"; + } + std::cout << " found.\n"; + assert(found_node.is_a_node() == true); + + child_name = "report"; + found_node = root_node.FindChildElement(child_name); + std::cout << "Child element " << child_name; + if (!found_node.is_a_node()) + { + std::cout << " not"; + } + std::cout << " found.\n"; + std::cout.flush(); + assert(found_node.is_a_node() == false); + + // Find a child node three levels deep. + child_name = "book"; + found_node = root_node.FindChildElement(child_name); + assert(found_node.is_a_node() == true); + found_node = found_node.FindChildElement("titlepage"); + assert(found_node.is_a_node() == true); + found_node = found_node.FindChildElement("title"); // Two levels deeper + std::cout << "Name of title node = " << found_node.name() << "\n"; + std::cout << "Content of title node = " << found_node.content() << "\n"; + + // Find multple child nodes + + xml_node chapter_node; + + child_name = "book"; + found_node = root_node.FindChildElement(child_name); + + for (int i = 0; i < 6; i++) + { + chapter_node = found_node.FindChildElement("chapter", i); + if (chapter_node.is_a_node()) + { + std::cout << "Chapter node " << i << " found.\n"; + } + else + { + std::cout << "Chapter node " << i << " is not found.\n"; + } + + } + + return 0; +} + diff --git a/test/xml_find.exp b/test/xml_find.exp new file mode 100644 index 0000000..f62e36b --- /dev/null +++ b/test/xml_find.exp @@ -0,0 +1,13 @@ +Reading XML file xml_test01.xml +Root element is doc +Child element book found. +Child element report not found. +Name of title node = title +Content of title node = Andromeda Class Library +Chapter node 0 found. +Chapter node 1 found. +Chapter node 2 found. +Chapter node 3 is not found. +Chapter node 4 is not found. +Chapter node 5 is not found. +PASS xml_find (exit status: 0) diff --git a/test/xml_test01.xml b/test/xml_test01.xml new file mode 100644 index 0000000..a6dd12d --- /dev/null +++ b/test/xml_test01.xml @@ -0,0 +1,19 @@ + + + + + Andromeda Class Library + + + + + Chapter 1 + + + Chapter 2 + + + Chapter 3 + + +