Created
July 14, 2015 21:42
-
-
Save hakre/c36a66708259f54e564a to your computer and use it in GitHub Desktop.
Recursive Method Calls with SimpleXML and DOMDocument Context
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Class ArrayXmlElement | |
* | |
* Use an array definition stored as XML to convert a tree structure from another DOMDocument | |
* | |
* @author hakre <http://hakre.wordpress.com> | |
*/ | |
class XmlArrayElement extends SimpleXMLElement | |
{ | |
/** | |
* setter for named fields on SimpleXMLElements | |
* | |
* @link https://hakre.wordpress.com/2015/03/27/the-simplexmlelement-magic-wonder-world-in-php/ | |
* | |
* @param string $name of the field | |
* @param mixed $value to store | |
*/ | |
public function setData($name, $value) | |
{ | |
$element = dom_import_simplexml($this); | |
$element->data[$name] = $value; | |
$element->circref = $element; | |
} | |
/** | |
* getter for named fields on SimpleXMLElements | |
* | |
* @link https://hakre.wordpress.com/2015/03/27/the-simplexmlelement-magic-wonder-world-in-php/ | |
* | |
* @param string $name of the field | |
* | |
* @return null|mixed retrieved value or null if field is not set | |
*/ | |
public function getData($name) | |
{ | |
$element = dom_import_simplexml($this); | |
if (!isset($element->data[$name])) { | |
return null; | |
} | |
return $element->data[$name]; | |
} | |
/** | |
* assign a document that is processed | |
* | |
* this also registers all xpath namespaces | |
* | |
* @param DOMDocument $doc to process | |
*/ | |
public function assignDocument(DOMDocument $doc) | |
{ | |
/** @var self $root */ | |
$root = $this->xpath('/*')[0]; | |
$xpath = new DOMXPath($doc); | |
foreach ($root->xml->namespace as $namespace) { | |
$xpath->registerNamespace($namespace['prefix'], $namespace['uri']); | |
} | |
$root->setData('xpath', $xpath); | |
} | |
public function toArray(DOMNode $context = null) | |
{ | |
/** @var self $root */ | |
$root = $this->xpath('/*')[0]; | |
if ($root == $this) { | |
return $this->array[0]->toArray(); | |
} | |
/** @var DOMXPath $xpath */ | |
$xpath = $root->getData('xpath'); | |
$return = []; | |
foreach ($this as $child) { | |
$result = $evaluated = $xpath->evaluate($child['expr'], $context); | |
if ($evaluated instanceof DOMNodeList) { | |
if (1 === $evaluated->length) { | |
$result = $child->toArray($evaluated->item(0)); | |
} else { | |
$result = []; | |
foreach ($evaluated as $node) { | |
$result[] = $child->toArray($node); | |
} | |
} | |
} | |
$name = (string)($child['alias'] ?: $child->getName()); | |
$return[$name] = $result; | |
} | |
// single elements can be casted to string | |
if ((1 === count($this)) and ('string' === (string)$child['cast'])) { | |
$return = reset($return); | |
} | |
return $return; | |
} | |
} |
Hi again Hakre! I'm still using your handy script. Would you kindly explain me how can I read the ID attribute of comma
given for example the following XML?
<articolato>
<articolo id="art1">
<num>Art. 1</num>
<comma id="art1-com1">
<corpo>Blah blah blah</corpo>
</comma>
</articolo>
</articolato>
Should'nt be as easy as this:
<comma expr="//comma/@id"/>
The expected result should be art1-com1
I can get the value of num
for example like this
<num expr="normalize-space(string(a:num))"/>
but I don't know how to get the id
attribute.
Thank you.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In your example the string "
Lorem ipsum...
" is the first text-child-node of the corpo element. It's no problem to retrieve it. When you're looking for the XML of the table, this would require returning the inner-XML which needs a modification. Xpath on it's own does not have a method to retrieve it, but the class could be extended to deal with it, perhaps similar as with the cast parameter.