CXML XMLS Compatibility

# XMLS Builder

Like other XML parsers written in Lisp, CXML can work with documents represented as list structures. The specific model implemented by cxml is compatible with the xmls parser. Xmls list structures are a simpler and faster alternative to full DOM document trees. They also serve as an example showing how to implement user-defined document models as an independent layer over the the base parser (c.f. xml/xmls-compat.lisp in the cxml distribution). However, note that the list structures do not include all information available in DOM documents (notably, things like dom:parent-node) and are sometimes more difficult to work with because of that since many DOM functions cannot be implemented on them.

New namespace handling: XMLS compatibility is not bug-for-bug-compatible with XMLS any more. There is now a mode using pairs of local name and namespace URI, and a second mode using qualified names only. The old behaviour using pairs of prefix and local names was removed.

Function CXML-XMLS:MAKE-XMLS-BUILDER (&key include-default-values include-namespace-uri) Create a SAX handler which builds XMLS list structures. If include-default-values is true, default values for attributes declared in a DTD are included as attributes in the xmls output. include-default-values is true by default and can be set to nil to suppress inclusion of default values.

If include-namespace-uri is true (the default), node names and attribute names are pairs of local name and namespace URI. (Except for attributes without a namespace, which are named using a string.) Otherwise, nodes and attributes are named by their qualified name.

Example:

    (cxml:parse-file "test.xml" (cxml-xmls:make-xmls-builder))

Function CXML-XMLS:MAP-NODE (handler node &key include-xmlns-attributes include-namespace-uri) Traverse an XMLS document/node and call SAX functions as if an XML representation of the document were processed by a SAX parser.

Use this function to serialize XMLS data. For example, we could define a replacement for xmls:write-xml like this:

    (defun write-xml (stream node &key indent)
      (let ((sink (cxml:make-character-stream-sink
                   stream :canonical nil :indentation indent)))
        (cxml-xmls:map-node sink node)))

Function CXML-XMLS:MAKE-NODE (&key name ns attrs children) => xmls node Build a list node of the form (name ((name value)*) child*).

The node list's car can also be a cons of local name and namespace prefix ns.

Accessor CXML-XMLS:NODE-NAME (node) Accessor CXML-XMLS:NODE-NS (node) Accessor CXML-XMLS:NODE-ATTRS (node) Accessor CXML-XMLS:NODE-CHILDREN (node) Accessors for xmls node data.

Accessor CXML-XMLS:MAKE-XPATH-NAVIGATOR () Creates a navigator object for use with Plexippus XPath.

Note that the navigator object caches parts of the document structure, so when re-using a navigator across XPath evalutions, make sure not to modify the list structure.

Example:

    CL-USER> (defparameter *test-document*
    	   (cxml:parse
                "<foo a='b'>
                   <a id='1'/> <b id='2'/> <c id='3'/>
                   <a id='4'/> <b id='5'/> <c id='6'/>
                   <a id='7'/> <b id='8'/> <c id='9'/>
                   <last/>
                 </foo>"
    	    (cxml-xmls:make-xmls-builder)))
    *TEST-DOCUMENT*

    CL-USER> (let ((xpath:*navigator* (cxml-xmls:make-xpath-navigator)))
    	   (xpath:evaluate "//c[position()=2]|//a[@id='1']"
    			   *test-document*))
    #<XPATH:NODE-SET (a ((id 1))), ... {27C751F1}>

    CL-USER> (xpath:all-nodes *)
    (("a" (("id" "1"))) ("c" (("id" "6"))))