Skip to content

Instantly share code, notes, and snippets.

@garagesocial
Last active November 1, 2016 14:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save garagesocial/32334d9af04dfc0112fd to your computer and use it in GitHub Desktop.
Save garagesocial/32334d9af04dfc0112fd to your computer and use it in GitHub Desktop.
Create etrepat/baum Header from XML Defined Hierarchy
<?php
/**
* Create headers from an xml string consisting of a hierarchy of nodes with attributes
* (ex: <header name="A"> <header name="AB" /> <header name="AC"> <header name="AD" /> </header> </header>
*
* @param string $content XML string containing hierarchy of nodes
* @return void
*/
public function hfxParseContent($content) {
$xml = new SimpleXMLElement($content);
$nodeDictionaryHierarchy = array ();
$nodeDictionaryData = array();
// parse and evaluate xml hierarchy
$this->hfxHierarchyParser($xml, $nodeDictionaryHierarchy, $nodeDictionaryData);
// process evaluated hierarchy and create headers
$this->hfxHeaderCreator($nodeDictionaryHierarchy, $nodeDictionaryData);
}
/**
* Parse XML and return hierarchy of immediate child. Each node in this hierarchy is represented by it's $uniqueKey
* (ex returned: array('A' => array('AB', 'AC'), 'AB' => array(), 'AC' => array('AD'), 'AD' =>array() )
*
* @param SimpleXMLElement $node Starting node
* @param array &$nodeDictionaryHierarchy Array of node identifier with child header identifier
* array('A' => array('AB', 'AC'), ...)
* @param array &$nodeDictionaryData Array of each header with corresponding attributes
* array('A' => array('name' => 'A', 'slug' => 'a'), ...)
* @param string $nodeName XML node names
* @param string $uniqueKey Unique attribute to use to identify each node (internal)
* @return void
*/
private static function hfxHierarchyParser($node, &$nodeDictionaryHierarchy, &$nodeDictionaryData, $nodeName = 'header', $uniqueKey = 'name') {
// each node needs initialization as an array to hold array of child nodes
if (array_key_exists("{$node[$uniqueKey]}", $nodeDictionaryHierarchy) === false) {
$nodeDictionaryHierarchy["{$node[$uniqueKey]}"] = array ();
$nodeDictionaryData["{$node[$uniqueKey]}"] = self::xml2array($node->attributes());
}
// check if node has child nodes
$nodeNode = $node->$nodeName;
if (isset($nodeNode)) {
// push each immediate child to the current node array represented by it's $uniqueKey
for ($key = 0; ($key < $nodeNode->count()); $key++) {
$header = $nodeNode[$key];
if (!in_array("{$node[$uniqueKey]}", $nodeDictionaryHierarchy["{$node[$uniqueKey]}"])) {
$nodeDictionaryHierarchy["{$node[$uniqueKey]}"][] = "{$header[$uniqueKey]}";
}
// recurse through next level down
self::hfxHierarchyParser($header, $nodeDictionaryHierarchy, $nodeDictionaryData);
}
}
}
/**
* Create and link headers from the hierarchy array
*
* @param array $nodeDictionaryHierarchy
* @param array $nodeDictionaryData
* @return void
*/
private static function hfxHeaderCreator(&$nodeDictionaryHierarchy, &$nodeDictionaryData) {
$headersPool = array();
foreach ($nodeDictionaryHierarchy as $nodeKey => $childNodeKeys) {
// create header
if (!array_key_exists($nodeKey, $headersPool)) {
$nodeData = $nodeDictionaryData[$nodeKey];
$headersPool[$nodeKey] = Header::create($nodeData);
}
// loop through each child of the header
foreach($childNodeKeys as $childNodeKey) {
// create child header
if (!array_key_exists($childNodeKey, $headersPool)) {
$childNodeData = $nodeDictionaryData[$childNodeKey];
$headersPool[$childNodeKey] = Header::create($childNodeData);
}
// set as child
$headersPool[$childNodeKey]->makeChildOf($headersPool[$nodeKey]);
}
}
}
/**
* Convert SimpleXMLElement to array
* source: http://stackoverflow.com/questions/7778814/how-to-convert-simplexmlobject-into-php-array
*
* @param SimpleXMLElement $xml
* @return array
*/
public function xml2array($xml) {
$arr = array();
foreach ($xml as $element) {
$tag = $element->getName();
$e = get_object_vars($element);
if (!empty($e)) {
$arr[$tag] = $element instanceof SimpleXMLElement ? xml2array($element) : $e;
}
else {
$arr[$tag] = trim($element);
}
}
return $arr;
}
<?
$data = '
<header name="A" slug="a">
<header name="B" slug="b">
<header name="C" slug="c">
<header name="D" slug="d" />
</header>
</header>
</header>
';
$this->hfxParseContent($data);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment