DOMNode to DOMElement in php
我想将DOMNode对象从对getElementsByTagName()的调用转换为DOMElement,以便访问子元素上的getElementsByTagName()之类的方法。用任何其他语言,我都会进行转换,这很容易,但是经过一番快速浏览,PHP没有进行对象转换。所以我需要知道的是如何从DOMNode对象中获取DOMElement对象。
- 您是否检查过getElementsByTagName()是否实际返回带有if($ item instanceof DOMElement)之类的DOMElement对象?如果是不需要强制转换,则可以使用$ item,就像它是DOMElement一样
-
getElementsByTagName()返回DOMNodeList,我确实假设DOMNodeList是DOMNode的列表。我以为您必须强制转换的原因是,当我想执行相同的过程时,我必须强制转换为Java。
-
有趣的是,getElementById返回DOMElement,但是getElementsByTagName返回一个列表,其中每个项目都是DOMNode!
您无需执行任何操作,只需调用以下方法:
1 2 3 4 5
| $links = $dom->getElementsByTagName('a');
foreach ($links as $link) {
$spans = $link->getElementsByTagName('span');
} |
顺便说一句,DOMElement是DOMNode的子类。如果您正在谈论DOMNodeList,则可以使用上述foreach()循环,或者通过使用DOMNodeList的item()方法,来访问此类列表中的元素。铅>
1
| $link_0 = $dom->getElementsByTagName('a')->item(0); |
- DOMNodeList是否会返回不是DOMElement的DOMNode吗?文档只是说DOMNode而没有提到DOMElement。例如,如果DOMNodeList来自DOMXPath :: query怎么办?
-
@ user2016290是的,DOMXPath::query甚至是DOMNode::childNodes。 gist.github.com/igstan/9654eca0db804c8e87bd
-
DOMElement具有其他方法,这些方法在DOMNode中不可用。例如getAttribute()。并且,即使您在DOMNode上使用此方法,它也可以在PHP中使用,但不适用于您的IDE(在弹出方法列表中不可用)。所以问题就来了:如何从getElementsByTagName获取DOMElement
-
@Andrew getElementsByTagName返回DOMElement的DOMNodeList,这就是为什么将其称为get元素的原因。因此,在该列表的项目上调用DOMElement方法始终是安全的。如果IDE无法处理此问题,那将是一个单独的问题。 PHP不是Java,我们应该相应地对待它们或切换语言。
-
@Ionuè? G. Stan,您在PHP手册中有一些参考资料,说DOMNodeList包含DOMElement而不是DOMNode吗?该手册说,仅返回了DOMNodeList,而没有任何更多信息,该列表内的内容是什么。默认假设是它是DOMNode,但是我错过了有关DOMElement的任何提及
-
@Andrew DOMNodeList通常包含DOMNode,是的。但是getElementsByTagName返回的DOMNodeList仅包含DOMElement。尽管没有强调,该方法的文档却这样说:"此函数返回DOMNodeList类的新实例,其中包含具有给定本地标记名称的所有元素。"您还可以使用以下小脚本进行验证:gist.github.com/igstan/9654eca0db804c8e87bd。
-
@Andrew我知道IDE会为此抱怨而感到沮丧,但是恕我直言,这超出了PHP语言的范围。
-
@Ionuè? G. Stan对IDE不感到沮丧,它是可修复的。我只是想知道PHP(官方)的行为,因此可以调整IDE以使其正常运行。
这是我在项目中用来最小化IDE警告的方法。
1 2 3 4 5 6 7 8 9 10 11
| /**
* Cast a DOMNode into a DOMElement
*/
function cast_e(DOMNode $node) : DOMElement {
if ($node) {
if ($node->nodeType === XML_ELEMENT_NODE) {
return $node;
}
}
return null;
} |
我知道这主要是一个令人讨厌的IDE问题。
原因是$DOMNodeList->item(0)巫婆返回了DOMNode(或者至少是IDE认为如此)。
要解决此问题,您必须将$DOMDocument->getElementsByTagName( $tagName )->item($index)提取到自己的方法中。在DOCBlock中,将@return语句设置为DOMElement可以修复检查问题。
这至少在PHPStorm中有效。
您不需要进行任何显式的类型转换,只需检查DOMNode对象的nodeType是否为XML_ELEMENT_NODE。
PHP对此将非常满意。
如果使用PHPLint检查代码,则会注意到PHPLint抱怨在DOMNode对象上使用getElementsByTagName。要解决此问题,您需要跳过以下箍:
1 2
| /*.object.*/ $obj = $node;
$element = /*.(DOMElement).*/ $obj; |
然后,您将拥有正确类型的$ element变量,并且PHPLint没有投诉。
如果有人正在IntelliJ / PHPStorm中寻找更优雅的解决方案。我设法解决了这样的问题:
1 2 3 4 5 6 7 8 9 10
| 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 */
} |
我所有的代码都正确地假设DOMNode是DOMElement的超类,但也是DOMComment等。例如,当我需要DOMElement来使用getAttribute时,我会添加上面的check。