Как импортировать 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&nbsp;World</p>'; 

Хорошо, я могу обойти эту проблему, преобразовывая объекты xhtml в сущности Unicode, но это так уродливо …

Любая помощь ?

Спасибо заранее!

Связанный вопрос:

  • DOMDocument::validate() проблема (решена)

Проблема заключается в том, что DOM не знает, что он должен рассматривать DTH XHTML, если вы не подтвердили документ против него. Если вы этого не сделаете, DOM не знает никаких объектов, определенных в DTD, и никаких других правил в нем. К счастью, мы выяснили, как сделать валидацию в этом другом вопросе , поэтому вооруженные этими знаниями, которые вы можете сделать

 $document->validate(); // anywhere before importing the other DOM 

И затем импортируйте с

 $fragment = $document->createDocumentFragment(); $fragment->appendXML('<h1>Hello</h1><p>Hello&nbsp;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&nbsp;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&nbsp;World</p> 

потому что, когда вы загружаете документ в DOM, DOM перезапишет все, что вы сказали перед документом. Таким образом, при использовании load libxml (и, следовательно, SimpleXml, DOM и XMLReader) делает (do) не знаю, что вы имеете в виду 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);