TBMANLIB_Xml Package

Author: woeoio.

The TBMANLIB_Xml contributed package reads, changes and writes XML documents. It has the shape of a small DOM. A cXml object holds a document as a tree of cXmlNode objects, finds elements by a path such as library/book, and reads and writes the document as a string or as a UTF-8 file. The mXml module holds the node types, the error numbers and two functions that convert between strings and UTF-8 bytes. The package is written in twinBASIC and calls two functions of the Windows API for the conversion. This section documents version 1.0.0.0, published under the MIT licence.

Dim x As New cXml
x.CreateNew "library"
x.SetAttribute "library", "city", "Oslo"

Dim book As cXmlNode
Set book = x.AddElement("library", "book")
book.SetAttribute "id", "1"
x.SetElementText "library/book", "Dune"

Dim y As New cXml
y.Parse x.ToXmlString()
Debug.Print y.GetAttribute("library", "city")
Debug.Print y.GetElementText("library/book")
Debug.Print y.ToXmlString(False)
' Output:
' Oslo
' Dune
' <library city="Oslo"><book id="1">Dune</book></library>

What the package reads and writes

A document is read from a string by Parse, from a file by LoadFromFile, or started with CreateNew. The package supports:

  • elements and their attributes, with attribute values in double or single quotes;
  • text, comments and CDATA sections, each held as a node. Text that is only white space is kept;
  • the version and encoding of the XML declaration, which are read, kept and written;
  • reading and setting an element’s text and attributes, adding and removing elements, copying a document (Clone) and appending one to another (Merge);
  • writing the document compactly or with line breaks, with &, <, >, " and ' escaped;
  • files in UTF-8. A byte order mark is accepted when a file is read and always written.

The package does not support, in version 1.0.0.0:

  • DTDs and schemas. A DOCTYPE declaration is not read, and nothing is validated against a DTD or a schema. Validate only checks that elements and attributes have names;
  • XPath. A path is a list of element names separated by /, with no positions, attributes or wildcards; see Paths;
  • namespaces. A prefix is part of an element’s or attribute’s name, and no namespace is resolved;
  • entities defined in a DTD, and character references such as &#65;. The five predefined entities are decoded in attribute values and not in text;
  • processing instructions, which are skipped, and the standalone pseudo-attribute of the declaration;
  • encodings other than UTF-8 in files, whatever the declaration says;
  • checking that text is well formed. Parse accepts text that is not XML, elements that are not closed and end tags that name another element.

The ParseOption enumeration, with members such as PreserveWhitespace and ValidateOnParse, is declared by the module, but no member of the package reads it.

Failures

No member of the package ends a program with an error of its own. A member that cannot do its work returns False, Nothing, an empty string or an empty collection, and in the IDE writes a line that names the member to the Debug Console, for example Parse failed: XML string cannot be empty. The error stays in the Err object after the call. The error numbers are constants of mXml, and only ERR_EMPTY_DOCUMENT is used. Reporting failures has the details.

Classes and module

  • cXml – holds an XML document, reads it from a string or a file, finds, changes and adds elements by path, and writes it as a string or a file
    • Document – returns the document node
    • Encoding – returns or sets the encoding name of the declaration
    • Initialized – returns whether the object holds a document
    • RootElement – returns the root element
    • Version – returns or sets the XML version of the declaration
    • XmlString – returns or sets the text of the document that was last read
    • New – creates an object
    • AddElement – adds an empty element as the last child of an element
    • Clone – returns a copy of the document
    • CreateNew – replaces the document with a new one that has a root element
    • GetAttribute – returns an attribute of an element
    • GetElementText – returns the text inside an element
    • LoadFromFile – reads a document from a file
    • Merge – appends the content of another document
    • Parse – reads a document from a string
    • RemoveAttribute – removes an attribute
    • RemoveElement – removes an element
    • SaveToFile – writes the document to a file
    • SelectElement – returns the element that a path selects
    • SelectElements – returns every node with a given name
    • SetAttribute – sets an attribute
    • SetElementText – replaces the text of an element
    • ToXmlString – returns the document as text
    • Validate – checks that every element and attribute has a name
  • cXmlNode – one node of a document: an element, text, a CDATA section, a comment or the document itself
    • Attributes – holds the attributes as a list of names and values
    • ChildNodes – holds the nodes directly inside the node
    • Name – returns or sets the name
    • NodeType – returns or sets the kind of node
    • Parent – returns the node that holds this one
    • Value – returns or sets the text of a text node, a CDATA section or a comment
    • New – creates a node
    • GetAttribute – returns the value of an attribute
    • GetChildNode – returns the first child with a given name
    • GetChildNodesByName – returns all the children with a given name
    • RemoveAttribute – removes an attribute
    • SetAttribute – sets the value of an attribute
  • mXml – the node types, the parse options, the error numbers, the defaults and the UTF-8 conversion functions

The test module

The package also contains mXmlTests, a module of unit tests for cXml, which has no page of its own here. mXmlTests.RunAllTests runs 86 checks and writes a line for each to the Debug Console: [PASS] or [FAIL] and the check’s message, grouped under the name of the test. It ends with a summary of the totals, the pass rate and a closing line; in version 1.0.0.0 all 86 pass. Each test is also a public Sub of the module that can be run alone.

The checks compare one value at a time and do not exercise the cases listed under Defects in version 1.0.0.0: the test of self-closing tags tests that the output contains />, and the namespace test tests that Parse returns True. The file tests write test_output.xml in the current folder, and leave it there.

See Also

  • cXml class – the document
  • cXmlNode class – the nodes
  • mXml module – constants, enumerations and UTF-8 conversion
  • Experimental Packages – the packages from TWINSERV that are not yet ready for use in a program