PHP DomDocument HTML操作 [英] PHP DomDocument HTML Manipulation
问题描述
我有以下HTML。
< div id =container>
< div id =current>当前Div< / div>
< / div>
在PHP中使用DomDocument时,我试图在div之前向HTML添加一个额外的div b
$ b
< div id =container>
< div id =new> New Div< / div>
< div id =current>当前Div< / div>
< / div>
当我使用下面的代码时,它似乎在div中添加了div,ID为当前,但在此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 =当前>
< div id =new> New Div< / div>
当前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 =postaction =>
< input type =textname =usernameid =username/>
< / form>
< / div>
错误:
致命错误:未捕获异常'DOMException',其中'Not Found Error'
在index.php中:55堆栈跟踪:#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 // ENhttp://www.w3.org/TR/REC-html40/loose.dtd\">
< html>
< body>
< div id =container>
< div id =new> New Div< / div>
< div id =current>当前Div< / div>
< / div>
< / body>
< / html>
希望这有助于:)
编辑
引用您报告的问题...我看到问题: input#username
不是 div#container
的直接子元素,它是 form
的直接子元素。因此,您需要将表单
元素作为 DOMNode
对象,而不是它的父元素 div#容器
。最简单的方法是在表格
中添加一个id,并执行如下操作:
$ form = $ doc-> getElementById('form');
$ username = $ doc-> getElementById('username');
$ username-> setAttribute('value','输入用户名!');
var_dump($ doc-> saveHTML());
这是基于以下HTML。请注意,表单
元素有一个ID:
< div id = 容器 >
< form id =formmethod =postaction =>
< input type =textname =usernameid =username>
< / form>
< / div>
如果由于某种原因,您无法向表单元素添加id,则可以从<$ c
$ p $ //找到div#容器元素
$ container = $ doc-> getElementBy('id');
//找到所有div元素子元素的表单元素
$ forms = $ container-> getElementsByTagName('form');
if(0!== $ form-> length){
$ form = $ forms-> item(0);
}
//等等
编辑#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
,它有一个
最后值得注意的是, DOMDocument
DOCTYPE
和 html
和 body
标签;这就是XPath查询从 body
传递的原因。
I have the following HTML.
<div id="container">
<div id="current">Current Div</div>
</div>
Using DomDocument in PHP, I am trying to add an extra div to the HTML before the div with the id of "current".
<div id="container">
<div id="new">New Div</div>
<div id="current">Current Div</div>
</div>
When I use the following code, it appears to add the div inside the div with the id of "current", but before the content of this div.Can anyone tell me why this is and how I can get the results like the HTML above? (See HTML Issue Below)
Current 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 Issue
<div id="container">
<div id="current">
<div id="new">New Div</div>
Current Div
</div>
</div>
EDIT:
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>
Error:
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))
You can use 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());
This yields:
<!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>
Hope this helps :)
EDIT
Referring to your reported issue... I see the problem: input#username
is not an immediate child of div#container
, it's an immediate child of form
. So you need to get the form
element as a DOMNode
object, not its parent div#container
. Easiest way to do this is add an id to the form
and do something like this:
$form = $doc->getElementById('form');
$username = $doc->getElementById('username');
$username->setAttribute('value', 'Enter username!');
var_dump($doc->saveHTML());
This is based on the the following HTML. Note the form
element has an id:
<div id="container">
<form id="form" method="post" action="">
<input type="text" name="username" id="username">
</form>
</div>
If for some reason you cannot add an id to the form element, you can traverse from div#container
like so:
// 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.
EDIT #2
I almost forgot XPath... If you want to get more succinct/adventurous you can use DOMXPath::query()
to find DOM nodes:
$xpath = new DOMXPath($doc);
$form = $xpath->query('body/div[@id="container"]/form')->item(0);
$input = $xpath->query('body//input[@id="username"]')->item(0);
The XPath query syntax is pretty cryptic but powerful, I cannot say I'm an expert by any means, so I cannot speak for the efficiency of these queries. Also you might want to add error checking - the query
method returns a DOMNodeList
which has a length
property.
Finally it's worth noting that DOMDocument
decorates your HTML fragment with a DOCTYPE
and html
and body
tags; this is why the XPath query traverses from body
.
这篇关于PHP DomDocument HTML操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!