Используйте DomDocument для замены всех тегов заголовков тегами h4

Я использовал DomDocument для GetElementById. Он выбрал div. Мне нужно заменить все теги заголовков в этом div тегом h4.

Вы не уточнили в своем вопросе, какова конкретная проблема, с которой вы сталкиваетесь. Я бы предположил, что есть две части, которые могут вызвать некоторые вопросительные знаки.

Первый из них – как получить руку на всех элементах, которые вы хотите переименовать, а второй – на самом деле переименовать элемент.

Получить элементы заголовка DOMDocument

Итак, сначала сначала: Чтобы выбрать все элементы заголовка, вам нужно выбрать все теги, которые являются элементами заголовка (от h1 до h6) . В сочетании с условием, что они также должны быть дочерними элементами тега div с определенным атрибутом id, это кажется довольно сложной задачей. Однако с запросом xpath он остается просто прямым.

Пример для моих примеров кода Я выбрал id `" content ", и следующее выражение xpath запрашивает все элементы заголовка:

( //div[@id="content"]//h1 |//div[@id="content"]//h2 |//div[@id="content"]//h3 |//div[@id="content"]//h4 |//div[@id="content"]//h5 |//div[@id="content"]//h6 ) 

Если я запустил это на этом веб-сайте (прежде чем ответить), он создаст следующий список тегов:

 Found 8 elements: #00: <h1> #01: <h2> #02: <h2> #03: <h3> #04: <h3> #05: <h3> #06: <h2> #07: <h4> 

Поскольку это хорошо показывает, с запросом xpath может быть создан даже список различных элементов и с определенными условиями, такими как дочерние элементы div с идентификатором. Этот код с первого взгляда:

 $url = 'http://stackoverflow.com/questions/16307103/use-domdocument-to-replace-all-header-tags-with-the-h4-tags'; $dom = new DOMDocument(); $internalErrorsState = libxml_use_internal_errors(true); $dom->loadHTMLFile($url); libxml_use_internal_errors($internalErrorsState); $xpath = new DOMXPath($dom); $expression = ' ( //div[@id="content"]//h1 |//div[@id="content"]//h2 |//div[@id="content"]//h3 |//div[@id="content"]//h4 |//div[@id="content"]//h5 |//div[@id="content"]//h6 )'; $elements = $xpath->query($expression); echo "Found ", $elements->length, " elements:\n"; foreach ($elements as $index => $element) { printf(" #%02d: <%s>\n", $index, $element->tagName); } 

Переименование DOMElement

Итак, как насчет второй проблемы, о переименовании элементов?

DOMDocumet из коробки не поддерживает это. Существует метод stub ( DOMDocument::renameNode() , недокументированный в текущем руководстве PHP), но если вы его вызываете, вы получите предупреждение о том, что оно не реализовано:

Предупреждение: DOMDocument :: renameNode (): еще не реализовано

Вместо этого нужно перевернуть свою версию. И вот как это работает: поскольку вы не можете переименовать элемент с DOMDocument, все, что вы можете сделать, это создать новый элемент с переименованным именем и скопировать узел, чтобы переименовать все его атрибуты и дочерние элементы в него, а затем заменить его на переименован в мелкую копию. Это делается по следующему методу:

 /** * Renames a node in a DOM Document. * * @param DOMElement $node * @param string $name * * @return DOMNode */ function dom_rename_element(DOMElement $node, $name) { $renamed = $node->ownerDocument->createElement($name); foreach ($node->attributes as $attribute) { $renamed->setAttribute($attribute->nodeName, $attribute->nodeValue); } while ($node->firstChild) { $renamed->appendChild($node->firstChild); } return $node->parentNode->replaceChild($renamed, $node); } 

Приведя это вместе с циклом foreach сверху, рядом с выводом имен тегов, их также можно переименовать:

 $elements = $xpath->query($expression); echo "Found ", $elements->length, " elements:\n"; foreach ($elements as $index => $element) { printf(" #%02d: <%s>\n", $index, $element->tagName); dom_rename_element($element, 'h4'); ################################### } 

А потом, снова запрос на выражение xpath, приведет только к тэгам h4:

 $elements = $xpath->query($expression); echo "Found ", $elements->length, " elements:\n"; foreach ($elements as $index => $element) { printf(" #%02d: <%s>\n", $index, $element->tagName); } 

Вывод:

 Found 8 elements: #00: <h1> #01: <h2> #02: <h2> #03: <h3> #04: <h3> #05: <h3> #06: <h2> #07: <h4> 

Полный код-пример

Здесь полный код-пример и его вывод с первого взгляда:

 <?php /** * Use DomDocument to replace all header tags with the h4 tags * @link http://stackoverflow.com/q/16307103/367456 */ $url = 'http://stackoverflow.com/questions/16307103/use-domdocument-to-replace-all-header-tags-with-the-h4-tags'; $dom = new DOMDocument(); $internalErrorsState = libxml_use_internal_errors(true); $dom->loadHTMLFile($url); libxml_use_internal_errors($internalErrorsState); $xpath = new DOMXPath($dom); $expression = ' ( //div[@id="content"]//h1 |//div[@id="content"]//h2 |//div[@id="content"]//h3 |//div[@id="content"]//h4 |//div[@id="content"]//h5 |//div[@id="content"]//h6 )'; $elements = $xpath->query($expression); echo "Found ", $elements->length, " elements:\n"; foreach ($elements as $index => $element) { printf(" #%02d: <%s>\n", $index, $element->tagName); dom_rename_element($element, 'h4'); } $elements = $xpath->query($expression); echo "Found ", $elements->length, " elements:\n"; foreach ($elements as $index => $element) { printf(" #%02d: <%s>\n", $index, $element->tagName); } /** * Renames a node in a DOM Document. * * @param DOMElement $node * @param string $name * * @return DOMNode */ function dom_rename_element(DOMElement $node, $name) { $renamed = $node->ownerDocument->createElement($name); foreach ($node->attributes as $attribute) { $renamed->setAttribute($attribute->nodeName, $attribute->nodeValue); } while ($node->firstChild) { $renamed->appendChild($node->firstChild); } return $node->parentNode->replaceChild($renamed, $node); } 

Если вы попробуете это, вы можете заметить, что теперь, после моего ответа, количество элементов заголовка изменилось. Надеюсь, это полезно!