I want to convert a DOMNode
object from a call to getElementsByTagName()
to a DOMElement
in order to access methods like getElements
This is what I use in my project to minimize IDE warning.
/**
* Cast a DOMNode into a DOMElement
*/
function cast_e(DOMNode $node) : DOMElement {
if ($node) {
if ($node->nodeType === XML_ELEMENT_NODE) {
return $node;
}
}
return null;
}
I know this is mostly an annoying IDE problem.
The reason is $DOMNodeList->item(0)
witch returns a DOMNode ( or at least the IDE thinks so ).
To fix this you will have to Extract out the $DOMDocument->getElementsByTagName( $tagName )->item($index)
into a method of its own. In the DOCBlock you set the @return statement to DOMElement witch fixes the inspection problem.
This Works at least in PHPStorm.
If anyone is looking for a more elegant solution in IntelliJ/PHPStorm. I managed to solve the issue like this:
private function doSomething(DOMNode $child){
if(!$child instanceof DOMElement)
throw new Exception('DOMElement expected but got something else.');
$attr = $child->getAttribute('attr'); //recognized by PHPStorm now as DOMElement
/* and more code */
}
All my code corretly assumes DOMNode which is de super class of DOMElement but also DOMComment etc. When I need DOMElement to use getAttribute
for example, then I add above check.
You don't need to cast anything, just call the method:
$links = $dom->getElementsByTagName('a');
foreach ($links as $link) {
$spans = $link->getElementsByTagName('span');
}
And by the way, DOMElement
is a subclass of DOMNode
. If you were talking about a DOMNodeList
, then accessing the elements in such a list can be done, be either the method presented above, with a foreach()
loop, either by using the item()
method of DOMNodeList
:
$link_0 = $dom->getElementsByTagName('a')->item(0);
You don't need to do any explicit typecasting, just check if your DOMNode object has a nodeType of XML_ELEMENT_NODE
.
PHP will be perfectly happy with this.
If you use PHPLint to check your code you will notice that PHPLint complains about using getElementsByTagName
on a DOMNode object. To get around this you need to jump through the following hoop:
/*.object.*/ $obj = $node;
$element = /*.(DOMElement).*/ $obj;
Then you will have a $element variable of the correct type and no complaints from PHPLint.