PHP DOMElement :: getElementsByTagName - 无论如何只是为了获得直接匹配的孩子?

时间:2010-06-15 22:52:44

标签: php xml dom

有没有办法只检索通过调用DOMElement :: getElementsByTagName找到的直接子节点?例如,我有一个包含category元素的XML文档。该category元素具有子类别元素(具有相同的结构),例如:

<category>
    <id>1</id>
    <name>Top Level Category Name</name>
    <subCategory>
        <id>2</id>
        <name>Sub Category Name</name>
    </subCategory>
    ...
</category>

如果我有代表顶级类别的DOMElement,

$topLevelCategoryElement->getElementsByTagName('id');

将返回一个列表,其中包含所有'id'元素的节点,其中我只需要顶层的节点。在使用XPath之外的任何方法吗?

4 个答案:

答案 0 :(得分:15)

我不敢。你必须遍历孩子或使用XPath。

for ($n = $parent->firstChild; $n !== null; $n = $n->nextSibling) {
    if ($n instanceof DOMElement && $n->tagName == "xxx") {
        //...
    }
}

XPath和XML文件的示例:

$xml = ...;
$d = new DOMDocument();
$d->loadXML($xml);
$cat = $d->getElementsByTagName("subCategory")->item(0);
$xp = new DOMXpath($d);
$q = $xp->query("id", $cat); //note the second argument
echo $q->item(0)->textContent;

给出2

答案 1 :(得分:11)

这样的事情应该做

/**
 * Traverse an elements children and collect those nodes that
 * have the tagname specified in $tagName. Non-recursive
 *
 * @param DOMElement $element
 * @param string $tagName
 * @return array
 */
function getImmediateChildrenByTagName(DOMElement $element, $tagName)
{
    $result = array();
    foreach($element->childNodes as $child)
    {
        if($child instanceof DOMElement && $child->tagName == $tagName)
        {
            $result[] = $child;
        }
    }
    return $result;
}

修改:添加了DOMElement检查实例

答案 2 :(得分:2)

我不使用PHP,但如果PHP实际上将DOM API实现为specified the W3C,则需要在任何Node对象上都有一个childNodes属性。您应该能够遍历所有直接子项并测试其标记名称,以查看它们是否是您正在寻找的那个。根据树的外观,这可能比通过标记名称获取所有元素并测试树位置要慢,或者速度可能要快得多。

答案 3 :(得分:-1)

您可以使用===比较元素。这将避免实例化Xpath对象。

$dom = new DOMDocument();
$dom->loadXML($xmlString);

$return          = array();

//find your top level element
$topLevelElement = $dom->getElementsByTagName('category');
//find all `id` child elements recursively
$idElements      = $topLevelElement->getElementsByTagName('id');

if ($idElements->length > 0) {
    foreach ($idElements as $idElement) {
        if ($idElement->parentNode === $topLevelElement) {
            $return[]   = $idElement;
       }
    }
}

//$return now holds non nested child elements

根据XML文档的大小,您可能会发现Xpath的性能更好。然而,就优雅而言,这种解决方案更清洁。