Last Updated: February 25, 2016
·
1.121K
· tlackemann

A little more than simpleXML hack

Suppose you have the following xml file

<?xml version="1.0" ?>
<parent>
    <child>
      Some text
      <sub>more text</sub>
      continued text
    </child>
</parent>

Using SimpleXML gives you a result like this

SimpleXMLElement Object
(
    [child] =>
Some text

continued text
)

Weird. I wrote a quick hack to get around this. Comments welcome.

function parseXML($xml) {
    $xr = new XMLReader();
    $xr->open($xml);

    # Set variables for loop
    $array = array();
    $openParentNode = false;
    $openChildNode = false;
    $setNode = null;
    $parentNode = 'parent';
    $triggerNodes = array('child');

    while($xr->read()) {
      # If we hit the "parent" node, open it
      if ($xr->name == $parentNode && !$openParentNode) {
        $i = count($array);
        $openParentNode = true;
        $setNode = $parentNode;
        $array[$i][$parentNode] = array();
      } elseif ($xr->name == $parentNode && $openParentNode) {
        $openParentNode = false;
        $setNode = null;
      }

      # If the "parent" is open, process the title parameters
      if ($openParentNode && (in_array($xr->name, $triggerNodes) || $xr->nodeType == XMLReader::TEXT)) {
        # If one of the trigger nodes is hit, open it
        if (in_array($xr->name, $triggerNodes) && $xr->name != $setNode) {
          $openChildNode = true;
          $setNode = $xr->name;
        } elseif (in_array($xr->name, $triggerNodes) && $xr->name == $setNode) {
          $openChildNode = false;
          $setNode = $parentNode;
        }

        # Text node - throw it into the array
        if ($openChildNode && $xr->nodeType == XMLReader::TEXT) {
          $array[$i][$parentNode][$setNode] = (isset($array[$i][$parentNode][$setNode])) ? $array[$i][$parentNode][$setNode].$xr->value : $xr->value;
        }
      }
    }

    return $array;
  }