我有以下 HTML。
<div id="container">
<div id="current">Current Div</div>
</div>
在 PHP 中使用 DomDocument,我试图在 id 为“current”的 div 之前向 HTML 添加一个额外的 div。
<div id="container">
<div id="new">New Div</div>
<div id="current">Current Div</div>
</div>
当我使用下面的代码时,它似乎在 div 中添加了一个 id 为“current”的 div,但是在这个 div 的内容之前。谁能告诉我这是为什么以及我如何得到这样的结果上面的 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))
最佳答案
您可以使用 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
元素作为 DOMNode
对象,而不是其父级 div#container
。最简单的方法是向 form
添加一个 id 并执行如下操作:
$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
属性。
最后值得注意的是,DOMDocument
用 DOCTYPE
和 html
以及 body
标记装饰您的 HTML 片段;这就是 XPath 查询从 body
遍历的原因。
关于PHP DomDocument HTML 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19877802/