If you don't know how iterators work with the iXML library, please read the previous section Traversing the DOM tree with iterators first.
Iterators wouldn't be that useful it they wouldn't allow to customize the way they traverse the nodes. Quite often you will only be interested in nodes that meet certain criteria like tag names, attribute values etc. The W3C DOM Level 2 Working Draft therefore introduces the concept of filters.
Filters can be applied to iterators and specify selection criteria a node must match in order to be returned by an iterator. In other words, filters allow to apply a restricted view on the DOM tree of an XML document. As an example take a filter that only returns elements with the tag name "item".
The iXML library provides several, often required implementations or types of filters. With the ABAP Objects version of iXML you can unfortunately not define your own filters (as you can do with the C++ version). This restriction is due to the architectural concepts of the ABAP Objects version of iXML.
cl_ixml_node_filter instances can be created by calling one of the factory methods provided by the if_ixml_nodeinterface.
data: filter type ref to if_ixml_node_filter.
filter = document->create_filter_name( name = 'item' ).
Now, when creating an iterator (on any DOM data structure of course) simply pass your filter instance:
data: iterator type ref to if_ixml_node_iterator,
iterator = document->create_iterator_filtered( filter ).
* iterator code as usual:
node = iterator->get_next( ).
while not node is initial.
* do something with the 'item' nodes
...
node = iterator->get_next( ).
endwhile.
Very often the match criteria for a filtered iterator is more complex than what could be done with a single filter instance. iXML comes with a set of predefined filteres that allow you to combine two or more filters into a single one. The combining filters allow to apply a logical AND, OR or NOT operation on the filters they contain. An AND filter for example will only accept a node that matches all the filters it combines. An OR filter will only accept nodes that match at least one of the filters it combines. And a NOT filter will accept those nodes, that are rejected by the filter it contains. Here's an example to iterate over all "person" elements with an attribute "status" with value retired":
data: filter1 type ref to if_ixml_node_filter,
filter2 type ref to if_ixml_node_filter,
filter type ref to if_ixml_node_filter,
iterator type ref to if_ixml_node_iterator,
node type ref to if_ixml_node.
filter1 = document->create_filter_name( name = 'person' ).
filter2 = document->create_filter_attribute( name = 'status'
value = 'retired' ).
filter = document->create_filter_and( filter1 = filter1
filter2 = filter2 ).
iterator = document.create_Iterator_filtered( filter ).
* iterator code as usual:
node = iterator->get_next( ).
while not node is initial.
* all we get here are "person" elements with
* attribute status="retired"
...
...
node = iterator->get_next( ).
endwhile.
For your convenience the iXML library already defines the following filter types:
Ancestor |
One of the ancestor nodes (direct or indirect parent node) has to be accepted by the contained filter. |
And |
All of the contained filters must accept the node. |
Attribute |
Only elements with an attribute matching the name and optional value are accepted. |
Name |
Only nodes with the specified name are accepted by this filter. |
NodeType |
Only nodes of a specific node type (e.g. comment) are accepted. |
Not |
Only those nodes rejected by the contained filter are accepted. |
Or |
One of the containing filters must accept the node in order for this filter to accept it. |
Parent |
The parent node has to be accepted by the contained filter. |