2013-11-09 76 views
2

我有以下HTML。PHP DomDocument HTML操纵

<div id="container"> 
    <div id="current">Current Div</div> 
</div> 

在PHP中使用DomDocument,我试图添加一个额外的div到HTML前面的div与“当前”的ID。

<div id="container"> 
    <div id="new">New Div</div> 
    <div id="current">Current Div</div> 
</div> 

当我使用下面的代码,这似乎与“当前”的ID添加在div里面的DIV,但这个内容div.Can谁能告诉我,之前这是为什么,以及如何我可以得到像上面的HTML一样的结果? (见HTML发行下文)

当前PHP

$doc = new DOMDocument(); 
$doc->formatOutput = true; 

$doc->loadHTMLFile('index.html'); 

$head = $doc->getElementById('current'); 
$base = $doc->createElement('div', 'New Div'); 
$base->setAttribute('id', 'new'); 
echo $doc->saveHTML(); 

HTML问题

<div id="container"> 
    <div id="current"> 
     <div id="new">New Div</div> 
     Current Div 
    </div> 
</div> 

编辑:

PHP

$doc = new DOMDocument(); 
$doc->formatOutput = true; 

$doc->loadHTMLFile('index.html'); 
$container = $doc->getElementById('container'); 
$current = $doc->getElementById('username'); 
$new = $doc->createElement('div', 'New Div'); 

$new->setAttribute('id', 'new'); 
$container->insertBefore($new, $current); 
echo $doc->saveHTML(); 

HTML

<div id="container"> 
    <form method="post" action=""> 
     <input type="text" name="username" id="username" /> 
    </form> 
</div> 

错误:

Fatal error: Uncaught exception 'DOMException' with message 'Not Found Error' 
in index.php:55 Stack trace: #0 index.php(55): 
DOMNode->insertBefore(Object(DOMElement), Object(DOMElement)) 

回答

2

您可以使用DOMNode::insertBefore()

<?php 

$doc = new DOMDocument(); 
$doc->formatOutput = true; 
$doc->loadHTMLFile('index.html'); 

$container = $doc->getElementById('container'); 
$current = $doc->getElementById('current'); 
$new = $doc->createElement('div', 'New Div'); 

$new->setAttribute('id', 'new'); 
$container->insertBefore($new, $current); 

var_dump($doc->saveHTML()); 

这产生了:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html> 
    <body> 
     <div id="container"> 
      <div id="new">New Div</div> 
      <div id="current">Current Div</div> 
     </div> 
    </body> 
</html> 

希望这有助于:)

编辑

参考您报告的问题......我看到的问题:input#username不是div#container的直接子,它是form的直接子。因此,您需要将form元素作为DOMNode对象,而不是其父项div#container。要做到这一点最简单的方法是添加一个ID,form,做这样的事情:

$form = $doc->getElementById('form'); 
$username = $doc->getElementById('username'); 
$username->setAttribute('value', 'Enter username!'); 

var_dump($doc->saveHTML()); 

这是基于以下的HTML。注意form元素有一个id:

<div id="container"> 
    <form id="form" method="post" action=""> 
     <input type="text" name="username" id="username"> 
    </form> 
</div> 

如果由于某种原因,你不能一个ID添加到表单元素,你可以从div#container遍历像这样:

// find div#container element 
$container = $doc->getElementBy('id'); 
// find all form elements that are children of div#container 
$forms = $container->getElementsByTagName('form'); 

if (0 !== $forms->length) { 
    $form = $forms->item(0); 
} 

// etc. 

编辑#2

我差点忘了XPath ...如果你想获得更简洁/冒险,您可以用DOMXPath::query()找到DOM节点:

$xpath = new DOMXPath($doc); 
$form = $xpath->query('body/div[@id="container"]/form')->item(0); 
$input = $xpath->query('body//input[@id="username"]')->item(0); 

XPath查询语法是非常神秘而强大的,我不能说我以任何方式的专家,所以我不能说出这些查询的效率。您也可能想要添加错误检查 - query方法返回一个DOMNodeList,它具有length属性。

最后值得注意的是,DOMDocumentDOCTYPEhtmlbody标签修饰您的HTML片段;这就是XPath查询从body开始的原因。

+0

当引用输入文本框的id而不是id为“current”的div时,脚本如何中断? - 有什么不同? – Richy

+0

Hi Richy。它打破了?有趣的...你是否得到一个特定的错误?以下对我有用:'$ input = $ doc-> createElement('input'); $ input-> setAttribute('type','text'); $ input-> setAttribute('id','foo'); $ input-> setAttribute('value','bar'); $ container-> insertBefore($ input,$ current); ' –

+0

我已更新我的原始文章,以包含更多详细信息:) – Richy