The current DOM level 2 specification does not standardize any method to serialize or output the DOM tree to a file, URL or memory buffer though this is to be addressed in DOM level 3 and Xerces 2.x does support an initial implementation of this as documented here. However the code to print a DOM tree using DOM2 methods is not complicated and an example is shown here. This also shows the use of attributes and checking for the type of a node. A more rigorous program might also want to check for processing instructions.
Note the use of the isWhiteSpace() method. This is a KCML extension which checks to see if a text node value consists only of whitespace characters. Such nodes occur between tags if the original document had a tab or newline at that point. This is more useful than the DOM sanctioned IsIgnorableWhitespace() as it depends on the use of a DTD to define when whitespace is ignorable.
The example also shows the use of some constants which are defined in the object and thus displayed in the workbench function browser when the object is loaded.
DIM OBJECT x, OBJECT p, OBJECT doc, OBJECT elm, count, last=0
DIM _ELEMENT_NODE=1, _TEXT_NODE=3, _CDATA_SECTION_NODE=4, _COMMENT_NODE=8
OBJECT x = CREATE "dynamic", "dyndom"
OBJECT p = x.CreateParser()
p.DoSchema = TRUE
p.DoNamespaces = TRUE
p.parse("books.xml")
REM get the Document object
OBJECT doc = p.Document
REM get its root element
OBJECT elm = doc.DocumentElement
count = 'printnode(OBJECT elm, 0)
END
DEFSUB 'printnode(OBJECT n, level)
LOCAL DIM OBJECT e, t, count, i, acount, OBJECT alist, OBJECT a, b, nc
t = n.NodeType
REM print this node
SELECT CASE t
CASE _ELEMENT_NODE
REM tag
count = 1
PRINT TAB(level);"<";n.TagName$;
REM add any attributes
OBJECT alist = n.Attributes
IF (OBJECT alist <> NULL)
acount = alist.length
i = 0
WHILE (i < acount) DO
OBJECT a = alist.Item(i)
PRINT " ";a.NodeName$;"='";a.NodeValue$;"'";
i++
WEND
END IF
CASE _TEXT_NODE
REM text, use KCML ext fn to check for whitespace only nodes
IF (NOT n.isWhitespace()) THEN PRINT TAB(level + 4);n.NodeValue$
CASE _CDATA_SECTION_NODE
PRINT TAB(level);"<![CDATA[";n.NodeValue$;"]]>"
CASE _COMMENT_NODE
REM comment
PRINT TAB(level);"<!-- ";n.NodeValue$;" -->"
CASE ELSE
REM some other node
PRINT "node";t;"value '";n.NodeValue$;"'"
END SELECT
REM and print its children
OBJECT e = n.FirstChild
nc = 0
WHILE OBJECT e <> NULL DO
IF (nc++ == 0 AND t == _ELEMENT_NODE) THEN PRINT ">"
count += 'printnode(OBJECT e, level + 4)
OBJECT e = e.NextSibling
WEND
IF (t == _ELEMENT_NODE)
REM if no children we can use the short form of the tag
IF (nc == 0)
PRINT "/>"
ELSE
PRINT TAB(level);"</";n.TagName$;">"
END IF
END IF
RETURN count
END SUB
For other XML DOM examples click here.