Show TOC Anfang des Inhaltsbereichs

Hintergrunddokumentation Creating a DOM tree from scratch  Dokument im Navigationsbaum lokalisieren

There are times where parsing an XML document is not an option simply because there is no XML document yet. One way of building an XML document from scratch is to first create a DOM representation of the complete XML document and then ask this representation to render itself into an output stream. This section will cover the most important steps when building a DOM tree from scratch. What is said here also applies to modifying a DOM tree that has been parsed from an XML document, of course.

Creating a document to hold the DOM tree

We have already created a cl_ixml_document object before when looking at the parser. The same steps are necessary here. If you want to build an XML document you should start with the root of it: a document. Here's how to proceed:

data: document type ref to if_ixml_document.

document = g_ixml->create_document( ).

Since we don't plan to parse an input XML document, we don't need a cl_ixml_stream_factory instance or an input stream. Other than that you have now created a first XML document, which is unfortunately - but not for long - without any use because it's still empty. Now let's add some content to the document.

Adding elements to the DOM tree

In probably 99% of times your XML documents will simply consist of nested and unnested elements with character data as content. Here's how to create and append them to the document you instantiated before:

data: element type ref to if_ixml_element.

element = document->create_element( name = 'person' ).

The above statement created a new cl_ixml_element node with the element type (in XML jargon) person. Now you can append the new element to the document:

data: rc type i.

rc = document->append_child( element ).

If you would render the cl_ixml_document instance into an XML output stream, you would already get the following:

<?xml version="1.0"?>

<person/>

This doesn't look too exciting, so let's add two more element nodes, this time as content of the person element.

data: e2 type ref to if_ixml_element,

      e3 type ref to if_ixml_element.

e2 = document->create_element( name = 'firstname' ).

e3 = document->create_element( name = 'lastname' ).

 

rc = element->append_child( e2 ).

rc = element->append_child( e3 ).

Now the cl_ixml_document instance would look like this when rendered into an XML output stream:

<?xml version="1.0"?>

<person>

  <firstname/>

  <lastname/>

</person>

Adding text data to the DOM tree

The example above lacked some important detail: text data. Usually you want to get more than just tag names. The next step is therefore how to add that data.

Data is represented as cl_ixml_text nodes in the DOM tree. An element having not only child elements as content has cl_ixml_text nodes in its list of child nodes. Creating such a node is straightforward:

data: text1 type ref to if_ixml_text,

      text2 type ref to if_ixml_text.

text1 = document->create_text( 'Walt' ).

text2 = document->create_text( 'Whitman' ).

As with cl_ixml_element nodes we have to somehow add the new nodes to the tree, and of course it works exactly as before:

rc = e1->append_child( text1 ).

rc = e2->append_child( text2 ).

When rendered into an XML output stream, the result looks more like what we'd expect from an XML document:

<?xml version="1.0"?>

<person>

  <firstname>Walt</firstname>

  <lastname>Whitman</lastname>

</person>

Making life a little bit easier

Most of the time you will be doing pretty much what I outlined above: create an cl_ixml_element, instantiate another cl_ixml_element or cl_ixml_text node and finally append the latter to the first. By repeating these steps often enough, you will create a complete DOM tree.

Once you have realized that you will start to build your own little helper routine to combine the steps above. That's perfectly valid, I would have done the same. In fact, I have done it. Here's the more convenient way of creating these simple element structures from the previous examples.

data: element type ref to if_ixml_element,

      parent  type ref to if_ixml_element.

parent  = document->create_simple_element(

            name = 'person'

            parent = document ). " this is the root node!

element = document->create_simple_element(

            name = 'firstname'

            value = 'Walt'

            parent = parent )." parent is NOT initial!

element = document->create_simple_element(

            name = 'lastname'

            value = 'Whitman'

            parent = parent )." parent is NOT initial!

That's considerably shorter and has the same result:

<?xml version="1.0"?>

<person>

  <firstname>Walt</firstname>

  <lastname>Whitman</lastname>

</person>

Still, it may be necessary to understand the steps described in the beginning, because you might one day find out that you have to add a comment to a document, or a processing instruction, or an entity reference or ...

Adding attributes to elements

If you have taken a look at the source code of an HTML page you have most definitely seen elements with attributes. They are usually used to modify certain properties (not the value) of the element they belong to (choosing whether to make a value an attribute or the element content is a sometimes tricky decision). A typical example is an HTML table-tag where an attribute is used to determine the width of the border line drawn between table cells:

<table border="0" cellpadding="0" cellspacing="0">

  ...

</table>

Once you have a cl_ixml_element node, adding attributes is easy if all you want to do is adding simple name/value pairs. Here's how to add the attribute status with the value retired to an element:

rc = element->set_attribute( name = 'status' value = 'retired' ).

It's as simple as that.

Adding other nodes to the DOM tree

Adding other types of nodes - e.g. comments - to the DOM tree works exactly the same. The factory class to create the various nodes from is the cl_ixml_documentinstance. This class provides factory methods for all logical elements available in XML. Creating a Document Type Definition

The DOM Level 1 Specification of the W3C does not cover the representation of the Document Type Definition (DTD) of an XML document. I therefore extended the DOM with the necessary classes and interfaces to represent the complete structure and content of the DTD. In doing so I tried to stay close to how the specification most likely might have looked like (ok, I try to predict the future here and the W3C might proof me wrong).

In XML a DTD can contain element declarations, attribute list declarations, entity declarations and notation declarations (among others). For each of these constructs you'll find a node type (class/interface) in the iXML library. Each one provides methods to access and modify the associated information. As with the elements of a document, the constructs of the DTD are stored as a tree of nodes. So adding a new notation declaration requires creating a cl_ixml_notation_declnode, setting the appropriate properties and adding it to the proper parent node (in this case the cl_ixml_document_type node itself).

The DTD is represented as a cl_ixml_document_type node which can be retrieved if already existing by the following statement:

data: dtd type ref to if_ixml_document_type.

dtd = document->get_document_type( ).

In order to create a new cl_ixml_document_type node and then attach it to a cl_ixml_document node use the following statements:

data: dtd type ref to if_ixml_document_type.

dtd = document->create_document_type( ).

...

* create the content of the DTD

...

document->set_document_type( dtd ).

The cl_ixml_document_type also serves a the class factory for the node types of the DTD (e.g. cl_ixml_notation_decl).



Ende des Inhaltsbereichs