2013-10-30 16 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()'。 –

相关问题