XML_PullParser
A token-based interface to the PHP expat XML library
version 1.3.2
Myron Turner
Strategies 3: $which and XML_PullParser_getSequence

Contents         

array XML_PullParser_getSequence ([array $el = ""], [mixed $args = ""])

XML_PullParser_getSequence is designed to work with the functions that use the $which parameter. It takes two optional parameters.

The first parameter must be a tokenized array, which is an array returned by XML_PullParser_getToken, XML_PullParser_getElement, XML_PullParser_getChild, or one of several other token-returning functions. 1 If this parameter is absent, then the function will first look for the $current_element and if that hasn't been set then it will use the current token. One or both of these will have been preset internally. 2

The second parameter is a list of elements for inclusion in the returned sequence array. It is either a variable length list of names or an array of names. These will all be strings. If this parameter is absent then all the elements found in the first parameter (or the internal default array) are included in the returned array.

The return value is a numerically indexed array whose elements are associate arrays which store the names of the selected elements and their positions in the document. See the documentation for this method.

This method silently resets the $current_element to the tokenized array from which creates its sequencing array. You can set it back to its original value by saving the $current_element and calling XML_PullParser_resetCurrentElement() with the saved value. The original value of the $current_element is also saved internally by XML_PullParser_getSequence in $_save_current_element, so that the following call will also do the reset:

$parser->XML_PullParser_resetCurrentElement($parser->_save_current_element)

Following are a number of examples of how to use XML_PullParser_getSequence . The first of these illustrates its use in conjunction with XML_PullParser_getElement . 3 (We are still using the DNS example.)

Listing 10
 1.    $tags = array("entry");
 2.   $child_tags = array("server","ipaddress", "domain");
 3.
 4.   $parser = new XML_PullParser_doc($doc,$tags,$child_tags);
 5.
 6.   while($token = $parser->XML_PullParser_getToken())
 7.   {
 8.     $parser->XML_PullParser_getElement('server');
 9.     $seq =  $parser->XML_PullParser_getSequence();
10.
11.     for($i=0; $i  < count($seq); $i++) {
12.          list($server, $which) = each($seq[$i]);
13.
14.          $name = $parser->XML_PullParser_getText($server,$which);
15.          echo "Name: $name\n";
16.
17.          $ip = $parser->XML_PullParser_getAttributes($server,$which);
18.          echo "\tIP: " . $parser->XML_PullParser_getAttrVal('ip', $ip) . "\n";
19.      }
10.
21.    }

/*
 Result
        Name:  example_1.com
                IP: 192.168.10.1
        Name:  example_2.com
                IP: 192.168.10.2
        Name:  example_3.com
                IP: 192.168.10.3
*/

Line 8 stores the three server elements in the $current_element, and line 9 creates the sequence array, which we then loop through. Each element in the array is in turn an associative array of the form:

Element_Name => $which

In the present case, the first element would be "SERVER" => 1, the second "SERVER" => 2, etc. In line 14 the element name and its which value are passed into XML_PullParser_getText and in line 17 they are passed into XML_PullParser_getAttributes. Therefore, the two functions know the name of the element to address-- server -- and which element in the sequence of server elements.

To treat all of the elements in Entry, we would not call XML_PullParser_getElement. In that case, if XML_PullParser_getSequence is not passed the array parameter, it returns a sequencing array based on the current token. Listing 11 shows how this might be implemented using a switch statement.

Listing 11
 1.    while($token = $parser->XML_PullParser_getToken())
 2.    {
 3.
 4.      $seq =  $parser->XML_PullParser_getSequence();
 5.
 6.       for($i=0; $i  < count($seq); $i++) {
 7.          list($element, $which) = each($seq[$i]);
 8.
 9.          switch($element) {
12.            case 'IPADDRESS':
13.                echo "$element: $which\n";
14.                echo $parser->XML_PullParser_getText($element,$which) . "\n";
15.                break;
16.            case 'SERVER':
17.                echo "$element: $which\n";
18.                echo $parser->XML_PullParser_getText($element,$which) . "\n";
19.                $ip = $parser->XML_PullParser_getAttributes($element,$which);
20.                echo "\tIP: " . $parser->XML_PullParser_getAttrVal('ip', $ip) . "\n";
21.                break;
22.            case 'DOMAIN':
23.                echo "$element: $which\n";
24.                echo $parser->XML_PullParser_getText($element,$which) . "\n";
25.                break;
26.            case 'ALIAS':
27.                echo "$element: $which\n";
28.                echo $parser->XML_PullParser_getText($element,$which) . "\n";
29.                break;
30.            default:
31.                echo "default: $element: $which\n";
32.
33.         }
34.      }
35.
35.   }

/* Result
    default: ENTRY: 1
    IPADDRESS: 1
     172.20.19.6
    DOMAIN: 1
     example.com
    SERVER: 1
     example_1.com
            IP: 192.168.10.1
    SERVER: 2
     example_2.com
            IP: 192.168.10.2
    SERVER: 3
     example_3.com
            IP: 192.168.10.3
    ALIAS: 1
     www.example.com
*/

It is worth noting here that the switch statement use upper case for each of the case statements. The PHP XML facility defaults to upper case for all element and attribute names. This can be changed in XML_PullParser by calling the package level function XML_PullParser_caseSensitive with a value of true. 4

Notes
1. See Tokenizing Functions
2. The array parameter is required only if the second parameter is absent.
3. A typical procedure would be to call XML_PullParser_getElement to select the elements of interest and then to call this function without any parameters.
4. It's possible to test for case using the class method XML_PullParser_isCaseFolded

Commentary
If XML_PullParser_getElement has been called and one wishes to treat the entire Entry structure, then pass XML_PullParser_getSequence the token returned from XML_PullParser_getToken. Or, make the current token the $current_element by calling: XML_PullParser_resetCurrentElement($token).
In the case of a complex database with mulitple repeated element names (like the DNS whois database), it is possible to gobble up the entire entry, as in Listing 11 , and then to successively shift the focus of interest by calling XML_PullParser_getElement with the appropriate element name, and then to use the result from XML_PullParser_getSequence to sequence through the multiples of that element.
It's instructive to note that the result in Listing 11 occurs in document order, beginning with Entry and ending with Alias.