Как импортировать строку XML в PHP DOMDocument
например, я создаю DOMDocument
вот так :
<?php
$implementation = new DOMImplementation();
$dtd =
$implementation->createDocumentType
(
'html', // qualifiedName
'-//W3C//DTD XHTML 1.0 Transitional//EN', // publicId
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-'
.'transitional.dtd' // systemId
);
$document = $implementation->createDocument('', '', $dtd);
$elementHtml = $document->createElement('html');
$elementHead = $document->createElement('head');
$elementBody = $document->createElement('body');
$elementTitle = $document->createElement('title');
$textTitre = $document->createTextNode('My bweb page');
$attrLang = $document->createAttribute('lang');
$attrLang->value = 'en';
$document->appendChild($elementHtml);
$elementHtml->appendChild($elementHead);
$elementHtml->appendChild($attrLang);
$elementHead->appendChild($elementTitle);
$elementTitle->appendChild($textTitre);
$elementHtml->appendChild($elementBody);
Итак, теперь, если у меня есть такая строка xhtml:
<?php
$xhtml = '<h1>Hello</h1><p>World</p>';
как я могу импортировать его в <body>
узел моего DOMDocument
?
пока единственное решение, которое я нашел, это что-то вроде этого :
<?php
$simpleXmlElement = new SimpleXMLElement($xhtml);
$domElement = dom_import_simplexml($simpleXmlElement);
$domElement = $document->importNode($domElement, true);
$elementBody->appendChild($domElement);
это решение кажется очень плохим для меня и создает некоторые проблемы, например, когда я пытаюсь с такой строкой:
<?php
$xhtml = '<p>Hello World</p>';
хорошо, я могу обойти это проблема с преобразованием объектов xhtml в объекты Unicode, но это так уродливо...
помочь ?
спасибо заранее !
вопрос :
2 ответов
проблема в том, что DOM не знает, что он должен рассматривать XHTML DTD, если вы не проверили документ против него. Если вы этого не сделаете, DOM не знает никаких сущностей, определенных в DTD, и никаких других правил в нем. К счастью, мы разобрались, как сделать проверку в этом другом вопрос, поэтому вооружившись этим знанием, вы можете сделать
$document->validate(); // anywhere before importing the other DOM
а затем импортировать с
$fragment = $document->createDocumentFragment();
$fragment->appendXML('<h1>Hello</h1><p>Hello World</p>');
$document->getElementsByTagName('body')->item(0)->appendChild($fragment);
$document->formatOutput = TRUE;
echo $document->saveXml();
выходы:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>My bweb page</title>
</head>
<body>
<h1>Hello</h1>
<p>Hello World</p>
</body>
</html>
другой способ импорта XML в другой DOM должен использовать
$one = new DOMDocument;
$two = new DOMDocument;
$one->loadXml('<root><foo>one</foo></root>');
$two->loadXml('<root><bar><sub>two</sub></bar></root>');
$bar = $two->documentElement->firstChild; // we want to import the bar tree
$one->documentElement->appendChild($one->importNode($bar, TRUE));
echo $one->saveXml();
выходы:
<?xml version="1.0"?>
<root><foo>one</foo><bar><sub>two</sub></bar></root>
однако это не может работать с
<h1>Hello</h1><p>Hello World</p>
потому что, когда вы загружаете документ в DOM, DOM перезапишет все, что вы сказали ему раньше о документе. Таким образом, при использовании load libxml (и, следовательно, SimpleXml, DOM и XMLReader) не знает, что вы имеете в виду XHTML. И он не знает никаких определенных в нем сущностей и вместо этого будет расплываться о них. Но даже если строка не будет содержать сущности, это недопустимый XML, поскольку в нем отсутствует корневой узел. Вот почему вы используете фрагмент.
можно использовать DomDocumentFragment для этого:
$fragment = $document->createDocumentFragment();
$fragment->appendXml($xhtml);
$elementBody->appendChild($fragment);
вот и все...
Edit: Ну, если у вас должен быть xhtml (вместо действительного xml), вы можете сделать это грязное обходное решение:
function xhtmlToDomNode($xhtml) {
$dom = new DomDocument();
$dom->loadHtml('<html><body>'.$xhtml.'</body></html>');
$fragment = $dom->createDocumentFragment();
$body = $dom->getElementByTagName('body')->item(0);
foreach ($body->childNodes as $child) {
$fragment->appendChild($child);
}
return $fragment;
}
использование:
$fragment = xhtmlToDomNode($xhtml);
$document->importNode($fragment, true);
$elementBody->appendChild($fragment);