The xml parser is your friend, let it parse the xml and handle the tokens as they appear. This just builds an array of the tags, but you can modify the element handlers or do whatever you want with the array when it's finished:
<?php
// do this when a start token is found by the parser
//
function startElement($parser, $tag, $attrs) {
global $parent, $inParent;
switch ($tag) {
case "BIRTH-DATE":
case "START-DATE":
case "END-DATE":
$parent[$tag] = array();
$inParent = $tag;
break;
case "YEAR":
case "MONTH":
case "DAY":
if (isset($inParent) ) {
$parent[$inParent][$tag] = true;
}
break;
}
return 0;
}
// do this when an end token is found by the parser
//
function endElement($parser, $tag) {
global $parent, $inParent;
switch ($tag) {
case "BIRTH-DATE":
case "START-DATE":
case "END-DATE":
$inParent = null;
break;
}
}
// these handlers are not used for anything in this example
//
function characterData($parser, $data) {
return 0;
}
function PIHandler($parser, $data) {
return 0;
}
function defaultHandler($parser, $data) {
return 0;
}
// set up the parser object and feed it the xml
//
function parse_date($xml) {
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
xml_set_processing_instruction_handler($xml_parser, "PIHandler");
xml_set_default_handler($xml_parser, "defaultHandler");
if (!xml_parse($xml_parser, $xml, false)) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
xml_parser_free($xml_parser);
}
// start with an empty array, not inside any parent tag
$parent = array();
$inParent = null;
$theXML = "<dates>
<birth-date>
<year></year>
<month></month>
<day></day>
</birth-date>
<start-date>
<year></year>
<month></month>
<day></day>
</start-date>
<end-date>
<year></year>
<month></month>
<day></day>
</end-date>
</dates>";
// parse the tokens
parse_date($theXML);
// display results
echo "<pre>";
print_r($parent);
echo "</pre>";
?>