PHP Conference Japan 2024

DOMDocument::createElement

(PHP 5, PHP 7, PHP 8)

DOMDocument::createElement创建新的元素节点

描述

public DOMDocument::createElement(string $localName, string $value = ""): DOMElement|false

此函数创建一个新的DOMElement类实例。除非使用(例如)DOMNode::appendChild()插入,否则此节点不会显示在文档中。

参数

localName

元素的标签名称。

value

元素的值。默认情况下,将创建一个空元素。也可以稍后使用DOMElement::$nodeValue设置值。

该值按字面使用,但<和>实体引用将被转义。请注意,&必须手动转义;否则它会被视为实体引用的开始。此外,“不会被转义。

返回值

返回一个新的DOMElement类实例,如果发生错误则返回false

错误/异常

DOM_INVALID_CHARACTER_ERR

如果localName包含无效字符,则引发此异常。

示例

示例 #1 创建一个新元素并将其作为根插入

<?php

$dom
= new DOMDocument('1.0', 'utf-8');

$element = $dom->createElement('test', 'This is the root element!');

//我们将新元素作为根插入(文档的子元素)
$dom->appendChild($element);

echo
$dom->saveXML();
?>

上面的示例将输出

<?xml version="1.0" encoding="utf-8"?>
<test>This is the root element!</test>

示例 #2 将包含未转义的 & 的文本作为 value 传递

<?php
$dom
= new DOMDocument('1.0', 'utf-8');
$element = $dom->createElement('foo', 'me & you');
$dom->appendChild($element);
echo
$dom->saveXML();
?>

上面的示例将输出类似于以下内容:

Warning: DOMDocument::createElement(): unterminated entity reference             you in /in/BjTCg on line 4
<?xml version="1.0" encoding="utf-8"?>
<foo/>

注释

注意:

value 将 *不会* 被转义。使用 DOMDocument::createTextNode() 创建具有 *转义支持* 的文本节点。

参见

添加注释

用户贡献的注释 9 条注释

14
mikek dot nospam at nospam dot muonics dot com
17 年前
关于下面关于需要htmlentities来避免关于未终止实体引用的警告的注释,我认为值得一提的是,使用createTextNode和DOMText::__construct不需要这样做。如果你混合使用这两种设置文本节点的方法,并且对所有要显示的数据(或不)一致地应用htmlentities,你将得到&amp;s(或警告和格式错误的xml)。

最好扩展DOMElement和DOMDocument,以便它创建一个DOMText节点并附加它,而不是将其传递给DOMElement构造函数。否则,祝你好运在你的代码中所有正确的地方使用(或不使用)htmlentities,尤其是在代码更改被进行的时候。

<?php

class XDOMElement extends DOMElement {
function
__construct($name, $value = null, $namespaceURI = null) {
parent::__construct($name, null, $namespaceURI);
}
}

class
XDOMDocument extends DOMDocument {
function
__construct($version = null, $encoding = null) {
parent::__construct($version, $encoding);
$this->registerNodeClass('DOMElement', 'XDOMElement');
}

function
createElement($name, $value = null, $namespaceURI = null) {
$element = new XDOMElement($name, $value, $namespaceURI);
$element = $this->importNode($element);
if (!empty(
$value)) {
$element->appendChild(new DOMText($value));
}
return
$element;
}
}

$doc1 = new XDOMDocument();
$doc1_e1 = $doc1->createElement('foo', 'bar & baz');
$doc1->appendChild($doc1_e1);
echo
$doc1->saveXML();

$doc2 = new XDOMDocument();
$doc2_e1 = $doc2->createElement('foo');
$doc2->appendChild($doc2_e1);
$doc2_e1->appendChild($doc2->createTextNode('bar & baz'));
echo
$doc2->saveXML();

?>

在createElement中指定的文本
<?xml version=""?>
<foo>bar &amp; baz</foo>

通过createTextNode添加的文本
<?xml version=""?>
<foo>bar &amp; baz</foo>
5
yasindagli at gmail dot com
15年前
要创建具有属性的元素,

<?php

function createElement($domObj, $tag_name, $value = NULL, $attributes = NULL)
{
$element = ($value != NULL ) ? $domObj->createElement($tag_name, $value) : $domObj->createElement($tag_name);

if(
$attributes != NULL )
{
foreach (
$attributes as $attr=>$val)
{
$element->setAttribute($attr, $val);
}
}

return
$element;
}

$dom = new DOMDocument('1.0', 'utf-8');

$elm = createElement($dom, 'foo', 'bar', array('attr_name'=>'attr_value'));

$dom->appendChild($elm);

echo
$dom->saveXML();

?>

输出
<?xml version="1.0" encoding="utf-8"?>
<foo attr_name="attr_value">bar</foo>
8
sergsokolenko at gmail dot com
17 年前
为避免警告信息“unterminated entity reference”,您可以使用htmlentities()转义提供的数值
<?php
//...
$dom->createElement('name', htmlentities($text))
//...
?>
6
funkathustra
12年前
虽然内置的DOM函数很棒,但由于它们旨在支持通用XML,因此生成HTML DOM变得特别冗长。我最终编写了这个函数来大幅加快速度。
无需调用类似以下内容
<?php
$div
= $dom->createElement("div");
$div->setAttribute("class","MyClass");
$div->setAttribute("id","MyID");
$someOtherDiv->appendChild($div);
?>
您可以使用以下方法实现相同的功能
<?php
$div
= newElement("div", $someOtherDiv, "class=MyClass;id=MyID");
?>
"key1=value;key2=value"语法使用起来非常快,但如果您的内容包含这些字符,则显然无法正常工作。因此,您也可以传递一个数组
<?php
$div
= newElement("div", $someOtherDiv, array("class","MyClass"));
?>
或者是一个数组的数组,表示不同的属性
<?php
$div
= newElement("form", $someOtherDiv, array(array("method","get"), array("action","/refer/?id=5");
?>

这是函数

<?php
function newElement($type, $insertInto = NULL, $params=NULL, $content="")
{
$tempEl = $this->dom->createElement($type, $content);
if(
gettype($params) == "string" && strlen($params) > 0)
{
$attributesCollection =split(";", $params);
foreach(
$attributesCollection as $attribute)
{
$keyvalue = split("=", $attribute);
$tempEl->setAttribute($keyvalue[0], $keyvalue[1]);
}
}
if(
gettype($params) == "array")
{
if(
gettype($params[0]) == "array")
{
foreach(
$params as $attribute)
{
$tempEl->setAttribute($attribute[0], $attribute[1]);
}
} else {
$tempEl->setAttribute($params[0], $params[1]);
}
}
?>
2
tschmieder at bitworks dot de
9年前
记住

如果您想对新节点执行多个操作,您可能需要在执行操作之前创建它的副本。

意思是
## 创建指向唯一内存块的地址!
$td = $dom->createElement('td');
## 修改原始唯一模式的一些内容
$td->setAttribute('class', 'saldo');

## 将唯一模式克隆成两个自己的
$td1 = clone $td;
$td2 = clone $td;

## 更改每个克隆节点的属性
$td1->nodeValue = 'Ich bin die erste neue Node';
$td2->nodeValue = 'Ich bin die zweite neue Node';

## 查找父元素
$tr = $dom->getElementById('t001-tr001');
## 查找第一个和最后一个子节点(此处仅为清晰起见)
$first = $tr->firstChild;
$last = $tr->lastChild;

## 创建新节点
$newtd1 = $tr->insertBefore($td1, $first);
$newtd2 = $tr->appendChild($td2);

结论
每次操作都需要一个原始的新节点!
3
lars dot c dot magnusson at gmail dot com
14年前
你可能会认为insertBefore和insertAfter是appendChild的直接替代方法,但事实并非如此。

<?php
$dom
= new DOMDocument();
$dom->load($file);

$dom->appendChild($newNode); //运行正常
$dom->insertBefore($newNode, $refNode); //将会失败

$refNode->parentNode->insertBefore($newNode, $refNode); // 感谢yasindagli (第一篇回复)
?>
4
estill at gvtc dot com
17 年前
请注意,第二个参数(值),虽然方便,但并非标准。你应该像这样创建元素:

<?php
$doc
= new DOMDocument('1.0', 'iso-8859-1');

$root = $doc->createElement('test');
$doc->appendChild($root);

$root_text = $doc->createTextNode('This is the root element!');
$root->appendChild($root_text);

print
$doc->saveXML();
?>

或者,也可以扩展DOMDocument类并添加你自己的自定义便捷方法,以避免干扰标准。

<?php
class CustomDOMDocument extends DOMDocument {
function
createElementWithText($name, $child_text) {
// 创建一个带有子文本节点的元素

// @param string $name 元素标签名
// @param string $child_text 子节点文本

// @return object 新元素

$element = $this->createElement($name);

$element_text = $this->createTextNode($child_text);
$element->appendChild($element_text);

return
$element;
}
}

$doc = new CustomDOMDocument('1.0', 'iso-8859-1');

$root = $doc->createElementWithText('test', 'This is the root element!');
$doc->appendChild($root);

print
$doc->saveXML();
?>

还要谨慎使用(或避免使用)'DOMElement->nodeValue' 属性。它可能会返回一些意外的值,并且更改其值会将元素的所有后代替换(删除)为单个文本节点。它也不是标准的;根据DOM规范,它应该返回NULL。
2
chris AT cmbuckley DOT co DOT uk
15年前
请注意,NUL字符“\0”不在$name的无效字符列表中,因此不会触发错误,但标签名将在空字节处被截断。

<?php

$dom
= new DOMDocument('1.0', 'utf-8');
$el = $dom->createElement('foo' . "\0" . 'bar', 'Hello World');
echo
$el->tagName; // 输出 "foo"

?>
-1
dignat at yahoo dot com
7年前
使用DomDocument创建元素并在值中转义&符号。

这样做

$element = new DOMDocument('1.0', 'UTF-8');

$test = $element->createElement('text');

$test ->appendChild($element->createElement('name'))
->appendChild($element->createtextNode('& I am ampersand');
To Top