Show TOC Anfang des Inhaltsbereichs

Hintergrunddokumentation Traversing the DOM tree  Dokument im Navigationsbaum lokalisieren

So far we have dealt with how to create a DOM representation of an XML document. Now that we have such a representation - a DOM tree - you will usually want to do something with this tree. You obviously need a way to "walk" the tree, to traverse it. This section describes the basic means to access nodes in the DOM tree, the next section will cover iterators and filters, a more high-level approach to traversing the tree.

Getting access to the root element

As you have seen in the previous sections, a cl_ixml_documentinstance always holds the complete DOM tree. One of the immediate child nodes of the cl_ixml_document is the root element of the XML document. The following call will give you access to this node:

data: element type ref to if_ixml_element.

element = document->get_root_element( ).

Now you have a good starting point to look at the rest of the document content.

Getting access to a node's children

There are two ways to traverse the child nodes of a node, e.g. the cl_ixml_elementnodes of an cl_ixml_element node. One is to first navigate to the first child node and then ask this node to return the next (sibling) node. This approach looks like that:

data: child type ref to if_ixml_node.

child = element->get_first_child( ).

while not child is initial.

*  do something with the node

  child = child->get_next( ).

endwhile.

The W3C DOM also defined a method to return a list of nodes, a cl_ixml_node_listinstance providing index-based access to the child nodes of a node:

data: nodes type ref to if_ixml_node_list,

      child type ref to if_ixml_node,

      index type i.

nodes = element->get_children( ).

while i < nodes->get_length( ).

  child = nodes->get_item( index ).

* do something with the node

  index = index + 1.

endwhile.

Even though index-based access is guaranteed to perform in constant time (O(1)) for sequential indizes (e.g. 1,2,3,..,n or n,..,3,2,1), using cl_ixml_node_list for random-access will usually degrade to linear lookup (O(n)).

Recursively using one of the two approaches above will of course allow you to traverse the whole DOM tree.

Getting access to an element's attributes

cl_ixml_attribute nodes are not part of the DOM tree that can be accessed with the above methods. Attributes are stored only with cl_ixml_element nodes and can be retrieved this way:

data: attributes type ref to if_ixml_named_node_map,

      attribute  type ref to if_ixml_attribute,

      child      type ref to if_ixml_node,

      index      type i.

attributes = element->get_attributes( ).

if not attributes is initial.

  while i < attributes->get_length( ).

    child = attributes->get_item( index ).

  * cast the child down to an attribute!!

    attribute ?= child->query_interface( ixml_iid_attribute ).

  * do something with the attribute

    index = index + 1.

  endwhile.

endif.

If you want to find an attribute by name and not index, cl_ixml_named_node_mapallows you to do so as the following example will show:

data: attributes type ref to if_ixml_named_node_map,

      attribute  type ref to if_ixml_attribute,

      child      type ref to if_ixml_node.

attributes = element->get_attributes( ).

if not attributes is initial.

  child      = attributes->get_named_item( name = 'status' ).

  attribute  = child->query_interface( ixml_iid_attribute ).

endif.

Since this is something you will do quite often, there is a convenient shortcut method of the if_ixml_element interface:

data: attribute type ref to if_ixml_attribute.

attribute = element->get_attribute_node( name = 'status' ).

or if you want to get the string value of an attribute:

data: str type string.

str = element->get_attribute( name = 'status' ).

Finding an element by name

Sometimes you'll know there is exactly one element with a given tag name in the whole document or a sub-tree of the document. The easiest way to find that one (or the first occurrence of this) node can be done using the following statement:

data: node type ref to if_ixml_node.

node = document->find_from_name( name = 'person' ).

It is possible to restrict the search depth in the tree; the following example would search up to two levels below the given element:

data: node type ref to if_ixml_node.

node = element->find_from_name( name = 'firstname' depth = 2 ).

Collecting all elements with a given name

It might happen that you have an XML document and want to get easy access to all elements with a particular tag-name, e.g. all item elements in a salesorder document.

One way of getting easy access to these elements is asking for a collection containing references to those elements that match a specified name:

data: items type ref to if_ixml_node_collection.

items = document->get_elements_by_tag_name( name = 'item' ).

As with if_ixml_element::find_from_name() it is possible to apply the function to a sub-tree of the document and to restrict the depth of search:

data: items type ref to if_ixml_node_collection.

items = document->get_elements_by_tag_name( name = 'item' depth = 2 ).

In the next section about iterators we'll take a look at a slightly better approach than creating an intermediate collection of interface references.



Ende des Inhaltsbereichs