+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
============================
# 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])
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:
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
*****************************/
-static const char *RCSID = "$Id: utc.cpp,v 1.1 2002-09-28 06:58:45 arjen Exp $";
-
#include <time.h>
#include "date.h"
--- /dev/null
+
+#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;
+}
--- /dev/null
+#include <libxml/parser.h> // 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);
+
+};
+
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
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
--- /dev/null
+/*******************************************************
+ * Unit test for the xml class
+ *
+ * test reading and writing of xml files.
+ ******************************************************
+ *
+ */
+
+#include "xml.h"
+#include <assert.h>
+
+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;
+}
+
--- /dev/null
+/*******************************************************
+ * Unit test for the xml class
+ *
+ * test finding content in xml nodes
+ ******************************************************
+ *
+ */
+
+#include "xml.h"
+#include <assert.h>
+
+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;
+}
+
--- /dev/null
+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)
--- /dev/null
+<?xml version="1.0"?>
+<doc style="main.css">
+ <book>
+ <titlepage>
+ <title>Andromeda Class Library</title>
+ </titlepage>
+ <toc/>
+
+ <chapter>
+ <heading>Chapter 1</heading>
+ </chapter>
+ <chapter>
+ <heading>Chapter 2</heading>
+ </chapter>
+ <chapter>
+ <heading>Chapter 3</heading>
+ </chapter>
+ </book>
+</doc>