Класс DOMNode
(PHP 5)
Обзор классов
Свойства
- nodeName
-
Возвращает имя текущего узла
- nodeValue
-
Возращает значение текущего узла
- nodeType
-
Возвращает тип текущего узла. Возможные варианты возвращаемых значений nodeType перечисленны в разделе констатнты XML_xxx_NODE
- parentNode
-
Возвращает родительский узел текущего узла
- childNodes
-
Возвращает список DOMNodeList, содержащий всех потомков текущего узла. Если у узла нет потомков, возвращает пустой список DOMNodeList.
- firstChild
-
Возвращает первый дочерний узел текущего узла. Если у узла нет потомков, возвращает
NULL
. - lastChild
-
Возвращает последний дочерний узел текущего узла. Если у узла нет потомков, возвращает
NULL
. - previousSibling
-
Возвращает предыдущий узел непосредственно от текущего узла. Если такого узла нет, возвращает
NULL
. - nextSibling
-
Возвращает следующий узел после текущего узла. Если такого узла нет, возвращает
NULL
. - attributes
-
Возвращает объект DOMNamedNodeMap, содержащий атрибуты текущего узла (только если это DOMElement), иначе вернёт
NULL
. - ownerDocument
-
Возвращает корневой узел DOMDocument текущего узла.
- namespaceURI
-
Вернёт пространство имён текущего узла или
NULL
если оно не установленно. - prefix
-
Вернёт префикс текущего узла или
NULL
если оно не установленно. - localName
-
Возвращает локальное имя текущего узла.
- baseURI
-
Возвращает универсальный код ресурса (URI) текущего узела или
NULL
, если не удалось получить URI. - textContent
-
Этот атрибут возвращает текстовое содержимое текущего узла и его потомков
Примечания
Замечание:
Расширение DOM использует кодировку UTF-8. Используйте функции utf8_encode() и utf8_decode() для работы с текстами в кодировке ISO-8859-1 или функцию Iconv для других кодировок.
Содержание
- DOMNode::appendChild — Добавляет новый дочерний узел в конец списка потомков
- DOMNode::C14N — Canonicalize nodes to a string
- DOMNode::C14NFile — Canonicalize nodes to a file
- DOMNode::cloneNode — Клонирует узел
- DOMNode::getLineNo — Возвращает номер строки узла
- DOMNode::getNodePath — Получение XPath пути к узлу
- DOMNode::hasAttributes — Проверяет, содержит ли данный узел атрибуты
- DOMNode::hasChildNodes — Проверяет, содержит ли данный узел потомков
- DOMNode::insertBefore — Добавляет новый дочерний узел перед опорным узлом
- DOMNode::isDefaultNamespace — Проверяет, совпадает ли URI пространства имен узла с пространством имен по умолчанию
- DOMNode::isSameNode — Проверяет, являются ли два узла одним и тем же узлом
- DOMNode::isSupported — Проверяет, поддерживается ли заданное свойство в определенной версии
- DOMNode::lookupNamespaceURI — Получает URI пространства имен узла по префиксу
- DOMNode::lookupPrefix — Возвращает префикс пространства имен узла из URI пространства имен
- DOMNode::normalize — Нормализует узел
- DOMNode::removeChild — Удаляет дочерний узел из списка потомков
- DOMNode::replaceChild — Заменяет дочерний узел
- Введение
- Установка и настройка
- Предопределенные константы
- Examples
- Класс DOMAttr
- Класс DOMCdataSection
- Класс DOMCharacterData
- Класс DOMComment
- Класс DOMDocument
- Класс DOMDocumentFragment
- Класс DOMDocumentType
- Класс DOMElement
- Класс DOMEntity
- Класс DOMEntityReference
- Класс DOMException
- Класс DOMImplementation
- Класс DOMNamedNodeMap
- Класс DOMNode
- Класс DOMNodeList
- Класс DOMNotation
- Класс DOMProcessingInstruction
- The DOMText class
- Класс DOMXPath
- DOM Функции
Коментарии
This class has a getAttribute method.
Assume that a DOMNode object $ref contained an anchor taken out of a DOMNode List. Then
$url = $ref->getAttribute('href');
would isolate the url associated with the href part of the anchor.
And apparently also a setAttribute method too:
$node->setAttribute( 'attrName' , 'value' );
It took me forever to find a mapping for the XML_*_NODE constants. So I thought, it'd be handy to paste it here:
1 XML_ELEMENT_NODE
2 XML_ATTRIBUTE_NODE
3 XML_TEXT_NODE
4 XML_CDATA_SECTION_NODE
5 XML_ENTITY_REFERENCE_NODE
6 XML_ENTITY_NODE
7 XML_PROCESSING_INSTRUCTION_NODE
8 XML_COMMENT_NODE
9 XML_DOCUMENT_NODE
10 XML_DOCUMENT_TYPE_NODE
11 XML_DOCUMENT_FRAGMENT_NODE
12 XML_NOTATION_NODE
This class apparently also has a getElementsByTagName method.
I was able to confirm this by evaluating the output from DOMNodeList->item() against various tests with the is_a() function.
You cannot simply overwrite $textContent, to replace the text content of a DOMNode, as the missing readonly flag suggests. Instead you have to do something like this:
<?php
$node->removeChild($node->firstChild);
$node->appendChild(new DOMText('new text content'));
?>
This example shows what happens:
<?php
$doc = DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
echo "Content 1: ".$node->textContent."\n";
$node->textContent = 'new content';
echo "Content 2: ".$node->textContent."\n";
$newText = new DOMText('new content');
$node->appendChild($newText);
echo "Content 3: ".$node->textContent."\n";
$node->removeChild($node->firstChild);
$node->appendChild($newText);
echo "Content 4: ".$node->textContent."\n";
?>
The output is:
Content 1: old content // starting content
Content 2: old content // trying to replace overwriting $node->textContent
Content 3: old contentnew content // simply appending the new text node
Content 4: new content // removing firstchild before appending the new text node
If you want to have a CDATA section, use this:
<?php
$doc = DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
$node->removeChild($node->firstChild);
$newText = $doc->createCDATASection('new cdata content');
$node->appendChild($newText);
echo "Content withCDATA: ".$doc->saveXML($node)."\n";
?>
For clarification:
The assumingly 'discoverd' by previous posters and seemingly undocumented methods (.getElementsByTagName and .getAttribute) on this class (DOMNode) are in fact methods of the class DOMElement, which inherits from DOMNode.
See: class.domelement
Just discovered that node->nodeValue strips out all the tags
The issues around mixed content took me some experimentation to remember, so I thought I'd add this note to save others time.
When your markup is something like: <div><p>First text.</p><ul><li><p>First bullet</p></li></ul></div>, you'll get XML_ELEMENT_NODEs that are quite regular. The <div> has children <p> and <ul> and the nodeValue for both <p>s yields the text you expect.
But when your markup is more like <p>This is <b>bold</b> and this is <i>italic</i>.</p>, you realize that the nodeValue for XML_ELEMENT_NODEs is not reliable. In this case, you need to look at the <p>'s child nodes. For this example, the <p> has children: #text, <b>, #text, <i>, #text.
In this example, the nodeValue of <b> and <i> is the same as their #text children. But you could have markup like: <p>This <b>is bold and <i>bold italic</i></b>, you see?</p>. In this case, you need to look at the children of <b>, which will be #text, <i>, because the nodeValue of <b> will not be sufficient.
XML_TEXT_NODEs have no children and are always named '#text'. Depending on how whitespace is handled, your tree may have "empty" #text nodes as children of <body> and elsewhere.
Attributes are nodes, but I had forgotten that they are not in the tree expressed by childNodes. Walking the full tree using childNodes will not visit any attribute nodes.
Here is a little function that truncates a DomNode to a specified number of text characters. I use it to generate HTML excerpts for my blog entries.
<?php
function makehtmlexcerpt(DomNode $html, $excerptlength)
{
$remove = 0;
$htmllength = strlen(html_entity_decode($html->textContent, ENT_QUOTES, 'UTF-8'));
$truncate = $htmllength - $excerptlength;
if($htmllength > $excerptlength)
{
if($html->hasChildNodes())
{
$children = $html->childNodes;
for($counter = 0; $counter < $children->length; $counter ++)
{
$child = $children->item($children->length - ($counter + 1));
$childlength = strlen(html_entity_decode($child->textContent, ENT_QUOTES, 'UTF-8'));
if($childlength <= $truncate)
{
$remove ++;
$truncate = $truncate - $childlength;
}
else
{
$child = makehtmlexcerpt($child, $childlength - $truncate);
break;
}
}
if($remove != 0)
{
for($counter = 0; $counter < $remove; $counter ++)
{
$html->removeChild($html->lastChild);
}
}
}
else
{
if($html->nodeName == '#text')
{
$html->nodeValue = substr(html_entity_decode($html->nodeValue, ENT_QUOTES, 'UTF-8'), 0, $htmllength - $truncate);
}
}
}
return $html;
}
?>
In response to: alastair dot dallas at gmail dot com about "#text" nodes.
"#text" nodes appear when there are spaces or new lines between end tag and next initial tag.
Eg "<data><age>10</age>[SPACES]<other>20</other>[SPACES]</data>"
"data" childNodes has 4 childs:
- age = 10
- #text = spaces
- other = 20
- #text = spaces
Yet another DOMNode to php array conversion function.
Other ones on this page are generating too "complex" arrays; this one should keep the array as tidy as possible.
Note: make sure to set LIBXML_NOBLANKS when calling DOMDocument::load, loadXML or loadHTML
See: http://be2.php.net/manual/en/libxml.constants.php
See: http://be2.php.net/manual/en/domdocument.loadxml.php
<?php
/**
* Returns an array representation of a DOMNode
* Note, make sure to use the LIBXML_NOBLANKS flag when loading XML into the DOMDocument
* @param DOMDocument $dom
* @param DOMNode $node
* @return array
*/
function nodeToArray( $dom, $node) {
if(!is_a( $dom, 'DOMDocument' ) || !is_a( $node, 'DOMNode' )) {
return false;
}
$array = false;
if( empty( trim( $node->localName ))) {// Discard empty nodes
return false;
}
if( XML_TEXT_NODE == $node->nodeType ) {
return $node->nodeValue;
}
foreach ($node->attributes as $attr) {
$array['@'.$attr->localName] = $attr->nodeValue;
}
foreach ($node->childNodes as $childNode) {
if ( 1 == $childNode->childNodes->length && XML_TEXT_NODE == $childNode->firstChild->nodeType ) {
$array[$childNode->localName] = $childNode->nodeValue;
} else {
if( false !== ($a = self::nodeToArray( $dom, $childNode))) {
$array[$childNode->localName] = $a;
}
}
}
return $array;
}
?>
A function that can set the inner HTML without encoding error. $html can be broken content such as "<a ID=id20>ssss"
function setInnerHTML($node, $html) {
removeChildren($node);
if (empty($html)) {
return;
}
$doc = $node->ownerDocument;
$htmlclip = new DOMDocument();
$htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
$clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
while ($item = $clipNode->firstChild) {
$node->appendChild($item);
}
}
It would be helpful if docs for concrete properties mentioned readonly status of some properties:
"
ownerDocument
The DOMDocument object associated with this node.
"