Я обрабатываю XML-совместимый ввод XHTML с использованием XPATH в PHP следующим образом:
$xml=new DOMDocument();
$xml->loadXML(utf8_encode($temp));
[...]
$temp=utf8_decode($xml->saveXML());
Проблема, которая возникает, заключается в том, что узлы, которые могут не закрываться самостоятельно в соответствии со спецификациями HTML5, например
<textarea id="something"></textarea>
или div, чтобы использовать JS
<div id="someDiv" class="whaever"></div>
возвращаться как
<textarea id="something" />
а также
<div id="someDiv" class="whaever" />
Я в настоящее время обращаюсь к этому с помощью str_replace
, но это нонсенс, так как мне нужно соответствовать отдельным случаям. Как я могу решить это?
В то же время XPATH настаивает на выпуске
xmlns:default="http://www.w3.org/1999/xhtml
и на отдельных узлах, недавно созданных, он помещает такие вещи, как <default:p>
, Как мне остановить это, не прибегая к глупому поиску и заменить следующим образом:
$temp=str_replace(' xmlns:default="http://www.w3.org/1999/xhtml" '," ",$temp);
$temp=str_replace(' xmlns:default="http://www.w3.org/1999/xhtml"'," ",$temp);
$temp=str_replace('<default:',"<",$temp);
$temp=str_replace('</default:',"</",$temp);
?
РЕДАКТИРОВАТЬ: У меня действительно возникают проблемы с глупым поиском и заменой, и я не собираюсь атаковать выходной XHTML с помощью RegExp. Рассмотрим этот пример:
<div id="videoPlayer0" class="videoPlayerPlacement" data-xml="video/cp_IV_a_1.xml"/>
Очевидно, что самозакрывающиеся div недопустимы (по крайней мере, в одном контексте, где я не могу вывести как mime application / xhtml + xml, но вынужден использовать mime text / html), и во всех других случаях они не проверяются.
Извините за поздний ответ, но вы знаете … это было Рождество. : D
function export_html(DOMDocument $dom)
{
$voids = ['area',
'base',
'br',
'col',
'colgroup',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'];
// Every empty node. There is no reason to match nodes with content inside.
$query = '//*[not(node())]';
$nodes = (new DOMXPath($dom))->query($query);
foreach ($nodes as $n) {
if (! in_array($n->nodeName, $voids)) {
// If it is not a void/empty tag,
// we need to leave the tag open.
$n->appendChild(new DOMComment('NOT_VOID'));
}
}
// Let's remove the placeholder.
return str_replace('<!--NOT_VOID-->', '', $dom->saveXML());
}
В вашем примере
$dom = new DOMDocument();
$dom->loadXML(<<<XML
<html>
<textarea id="something"></textarea>
<div id="someDiv" class="whaever"></div>
</html>
XML
);
echo export_html($dom);
будет производить
<?xml version="1.0"?>
<html>
<textarea id="something"></textarea>
<div id="someDiv" class="whaever"></div>
</html>
Счастливого Рождества! ^ _ ^
Источники:
<?php
$content = '<root><textarea id="something"></textarea><div id="someDiv" class="whatever"></div><img src="your_src" /><br /><br /></root>';
$xml = new DOMDocument('1.0');
$xml->loadXML(utf8_encode($content));
$xml->formatOutput = true;
$temp=$xml->saveXML(NULL, LIBXML_NOEMPTYTAG);
$temp = utf8_decode($temp);
$closings = array('area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr');
foreach($closings AS $c){
$temp = str_replace('</'.$c.'>', '', $temp);
}
var_dump($temp);