# XML parsing

This chapter is dedicated to the XML parsing, a subpart of the standard xml processing module. XML parsing refers to the ability to read valid xml constructs from an input stream and build an internal representation that is suitable for later processing. This chapter is designed for handling basic XML representation and does not cover the operations performed by a XML processor, such like entity expansion or DTD validation.

All xml processing objects are located in the `afnix-xml` module. This module must be loaded prior any operation. Multiple calls to the module initialization routine are harmless. The interpreter method `library` loads a specific module by name. When the module has been loaded, the object are available in the `afnix:xml` nameset.

interp:library "afnix-xml"

## XML tree representation

A xml document is represented with a tree. At the top of the tree is the `XmlRoot` object. The root object is not part of the document, but acts as the primary container for other objects. Inside , a xml document starts with a root node and all other child elements are `XmlNode` objects.

### Node base object

The xml tree is built with the `XmlNode` object. The node object has different derivation depending on the required representation. For example, the `XmlRoot` object is derived from the `XmlNode` object. A node object can have child object unless the node is marked as an empty node. Trying to add node to an empty node results in an exception. A node can also be marked empty by the user. This situation typically arises with tag node which are used alone such like the <br/> xhtml empty tag or an empty paragraph <p/>. Although a xml node cannot be constructed directly, there is a predicate `node-p` that can be used to assert the node type.

# check a node assert true (afnix:xml:node-p node)

The `add-child` method adds a child node to the calling node. If the calling node is marked empty, an exception is raised when attempting to add the node. There is no limit for the number of nodes to add. In particular, when a text is to be added, care should be taken that there is no markup within that text. In doubt, the `parse` method should be used.

# parse a text and add 3 child nodes p:parse "The quick brown <b>fox</b> jumps over the lazy dog"

In the previous example, the first child node is a `XmlText` node with the value The quick brown . The second node is a `XmlTag` node with name b. Finally, the third node is also a `XmlText` node with the value jumps over the lazy dog. It should be noted that the tag node has a child `XmlText` node with the value fox. This example also illustrates the power of the `parse` method which considerably simplify the creation of a xml tree. Finally, there is a subtle subject to be treated later which concerns the use of character reference with the `parse` method. Like any other xml parser, character references are evaluated during the parsing phase, thus providing no mechanism to create such reference. For this reason, a special class called `XmlCref` is provided in the module.

### Tag object

The `XmlTag` class is one of the most important class as it holds most of the xml constructs. A tag is defined by a name, a set of attributes and eventually a content. In its simplest form, a tag is created by name. With an additional boolean parameter, the tag can be marked as an empty node.

# create an empty paragraph tag const p (afnix:xml:XmlTag "p" true)

Adding attributes to a tag is imply a matter of method call. The `add-attribute` method operates with a `Property` object while the `set-attribute` operates with a name and a literal value. As a matter of fact, the attributes are stored internally as a property list.

# <p class="text"> # create a paragraph tag const p (afnix:xml:XmlTag "p") # set the class attribute p:set-attribute "class" "text"

The node empty flag determines whether or not there is a end tag associated with a tag. If the empty flag is false, the node can have children nodes and is associated with a end tag. With the empty flag set, there is no child nodes. Such situation corresponds to the xml /> notation.

# <br/> # create a br empty tag const br (afnix:xml:XmlTag "br" true)

### Text objects

The xml module provides two types of xml text node. The basic object is the `XmlText` node which is designed to hold some text without markup. It is this kind of nodes which is automatically instantiated by the `parse` method, as described earlier. The other object is the `XmlData` which corresponds to the xml CDATA special markup. With a character data node, the characters are not interpreted, including those that indicate markup starts like < or end like >. The `XmlData` is particularly used to store scripts or other program text inside a xml description. As an example, it is recommended to use a character data node inside a script tag with xhtml.

## Document reading

A xml document is read by scanning an input stream an building a representation of the xml tree.

### The document object

The `XmlDocument` object is a special object is designed to ease the reading process of an xml document. The process of creating a xml document consists of creating a document object, then binding a xml reader, parsing the input stream and finally storing the root node. When the operation is completed, the root node is available in the document object.

# create a xml document const xdoc (afnix:xml:XmlDocument "example.xml") # get the root node const rppt (xdoc:get-root)

### The root node content

When a document is parsed, the root node holds all the elements and markup sequentially. At this stage, it shall be noted that the element data are not expanded. Unlike a normal XML reader, the parameter entity are kept in the node data, are expended later by the XML processor.