PHP DOM: как заменить узел DocumentType в моем документе XML?

Я пишу скрипт для очистки так называемого HTML-документа, который MS Word создает, когда вы сохраняете как «Web Page, Filtered». Я хочу, чтобы полученный документ был действительным XHTML1.

Первое, что я хочу сделать, это изменить! DOCTYPE, чтобы он был XHTML 1.0 Strict вместо ...4.0 Transitional,

Я написал код, который выглядел так, как будто он должен работать, но когда я запускаю его, я получаю Segmentation fault из PHP. Сначала я думал, что это происходит в save функция, но после добавления некоторых echo Заявления для отладки Теперь я думаю, что проблема в местах, отмеченных {{{1}}} а также {{{2}}} в коде (ниже).

Вот что я думаю: {{{1}}} Я перебираю DOMNodeList, обрабатывая его так, как если бы это был обычный массив, с которым я могу пройти foreach,

Но в {{{2}}} я меняю список подузлов родителя. Я подозреваю, что это ломает мою foreach: либо DOMNodeList или мой foreach указатель становится недействительным.

Итак, каков «правильный» способ внести изменения в дерево DOM, пока вы обойдете его? Я придумал два возможных варианта:

  1. Скопируйте DOMNodeList в обычный массив:

    $ nodelist = [];
    foreach ($ node-> childNodes как $ subnode) {
    $ nodelist [] = $ subnode;
    // Или, возможно, объект, который содержит соответствующий код и параметры для изменения, которое я хочу сделать
    }
    foreach ($ nodelist как $ subnode) {
    // сделать соответствующее изменение
    }

  2. Пройдите по дереву DOM, но не вносите никаких изменений. Вместо этого создайте массив всех мест, где я хочу внести изменения. Когда закончите, просмотрите этот массив и внесите изменения.

  3. Может быть, есть какой-то «официальный» способ сделать это ????

Соответствующие части моего кода ниже:

<?
$dom = new DOMDocument();
$dom->loadHTMLFile($htmFName);
$trav = new DOMTraverser($dom);

$storyParms = new StoryParams("some string");
$callback = new StoryDocCallback($htmFName);

$trav->traverse($callback, $storyParms);
$dom->save("y");

class DOMTraverser
{
private $docNode;
private $callback;
private $param;

public function __construct(DOMNode $node)
{
$this->docNode = $node;
}

public function traverse(GeneralCallBack $cb, $param)
{
$this->callback = $cb;
$this->param = $param;
$this->traverseNode($this->docNode);
}

public function traverseNode($node)
{
$this->callback->callBefore($node, $this->param);
if ($node->hasChildNodes()) {
{{1}}       foreach ($node->childNodes as $subnode) {
if($subnode != null) {
$this->traverseNode($subnode);
}
}
}
}
}

class StoryDocCallback implements GeneralCallback
{
public function callbefore($node, $param)
{
$name = $node->nodeName;
if (is_a($node, "DOMDocumentType")) {
$this->repairDocType($node);
return;
}
...
}

protected function repairDocType(DOMNode $node)
{
$impl = new DomImplementation();
$rootName = "html";
$pubID = "-//W3C//DTD XHTML 1.0 Strict//EN";
$sysID = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
$newDocType = $impl->createDocumentType($rootName, $pubID, $sysID);

$parent = $node->parentNode;
{{2}}   $rc = $parent->replaceChild($newDocType, $node);
assert($rc != false);
}
...
}

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]