2013-10-30 15 views
1

我需要一個快速的HTML解析器,用PHP編寫。首先,我嘗試了一些現有的解析器(如Ganon或QueryPath),但它們對於我的項目來說非常緩慢。最後我決定使用php內置的DOMDocument,這是所有內容中最快的。它只有一些裸露的方法。所以我不得不開始建立我自己的。如何在擴展DOMElement的自定義類中設置新的HTML標記(在PHP中使用DOMDocument)?

我正在寫一個擴展DOMElement的類。像'addText'這樣的新方法工作正常,但當我想要更改標籤名稱時遇到問題。

爲了更改標籤名稱,節點必須被替換。這是另一個節點。在此之後,任何進一步的操作不會再影響節點。

更新:現在,我已經添加在newTag方法return $newNode;和我使用這樣的:$node = $node->newTag('h1');但一致性我真的想只需使用:$node->newTag('h1');

請參閱代碼(簡化):

 <?php 


     class my_element extends DOMElement { 

      public function __construct() { parent::__construct();} 

      public function newTag($newTagName) { 

       $newNode = $this->ownerDocument->createElement($newTagName); 
       $this->parentNode->replaceChild($newNode, $this); 

       foreach ($this->attributes as $attribute) { 
        $newNode->setAttribute($attribute->name, $attribute->value); 
       } 
       foreach (iterator_to_array($this->childNodes) as $child) { 
        $newNode->appendChild($this->removeChild($child)); 
       } 
       //at this point, $newnode should become $this... How??? 


      } 

      //append plain text 
      public function addText ($text = '') { 
       $textNode = $this->ownerDocument->createTextNode($text); 
       $this->appendChild($textNode); 
      } 

      //... some other methods 
     } 


     $html = '<div><p></p></div>'; 

     $dom = new DOMDocument; 
     $dom->loadHTML($html); 
     $xPath = new DOMXPath($dom); 
     $dom->registerNodeClass("DOMElement", "my_element"); //extend DOMElement class 

     $nodes = $xPath->query('//p'); //select all 'p' nodes 
     $node = $nodes->item(0); // get the first 


    //Start to change the selected node 
    $node->addText('123'); 
    $node->newTag('h1'); 
    $node->addText('345'); //This is not working because the node has changed! 

    echo $dom->saveHTML(); 

此代碼將輸出<div><h1>123</h1></div>正如你所看到的,文字345未添加後,我改變了標籤名。

要繼續使用選定節點可以做些什麼?是否可以將新節點設置爲'newTag'方法中的當前節點?

回答

2

理想的解決方案是DOMDocument::renameNode(),但它尚未在PHP中提供。

也許這會工作,而不是,被稱爲$node = $node->parentNode->renameChild($node, 'h1')

<?php 

class MyDOMNode extends DOMNode { 
    public function renameChild($node, $name) { 
     $newNode = $this->ownerDocument->createElement($name); 

     foreach ($node->attributes as $attribute) { 
      $newNode->setAttribute($attribute->name, $attribute->value); 
     } 

     while ($node->firstChild) { 
      $newNode->appendChild($node->firstChild); 
     } 

     $this->replaceChild($newNode, $node); 

     return $newNode; 
    } 
} 
+0

是的,這是一個可行的解決方案。請參閱我的更新。但是你認爲不是使用'$ node = $ node-> newTag('h1');'有任何解決方案使它工作只是'$ node-> newTag('h1');'?不知怎的,沒有'return $ newNode;'。 – Victor

+0

據我所知,不使用'DOMDocument :: renameNode()'。 –

相關問題