2010-06-15 26 views
7

有沒有辦法只檢索通過調用DOMElement :: getElementsByTagName找到的直接子項?例如,我有一個包含category元素的XML文檔。該類別元件具有子類別的元件(其具有相同的結構),如:PHP DOMElement :: getElementsByTagName - 無論如何只獲得直接匹配的孩子?

<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之外的任何方式來做到這一點?

回答

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

+0

這實際上比我的SO-textbox函數草案更好。 (我忘了檢查的實例) – Kris 2010-06-15 23:03:45

+0

Darn,感謝您的解決方案 – 2010-06-15 23:04:29

+0

我再次爲增加的xpath解決方案upvote。選擇是好的 – Kris 2010-06-15 23:09:55

2

我不使用PHP,但是如果PHP實際上實現了DOM API爲specified the W3C,則需要在任何Node對象上使用childNodes屬性。你應該能夠遍歷所有的直接孩子,並測試他們的標籤名稱,看看他們是否是你正在尋找的。根據樹的外觀,這可能比通過標記名稱獲取所有元素並測試樹的位置要慢,或者可能會快得多。

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; 
} 

編輯:添加的instanceof一個DOMElement檢查

+0

謝謝,這很有幫助。我必須改變的一件事是'$ element-> children'到'$ element-> childNodes'。自答案發布後可能發生了一些變化。 – dontGoPlastic 2012-12-27 16:48:28

-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的性能更好。然而,就優雅而言,這種解決方案更清潔。

相關問題