3

我有以下 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 添加到 div 中,id 为“current”,但在此 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))
4

1 回答 1

3

您可以使用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对象,而不是它的 parent div#container。最简单的方法是添加一个 idform并执行以下操作:

$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()...

$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属性的 a。

最后值得注意的是,DOMDocumentDOCTYPEandhtmlbody标签装饰你的 HTML 片段;这就是 XPath 查询从body.

于 2013-11-09T15:58:17.780 回答