Подтвердить что ты не робот

Незаконное самозакрывание node обозначение для пустых узлов - вывод XHTML с PHP DOMDocument

Я обрабатываю 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);

?

EDIT: У меня действительно возникают проблемы с глупым поиском и заменой, и я не намерен атаковать выходной XHTML с помощью RegExp. Рассмотрим этот пример:

<div id="videoPlayer0" class="videoPlayerPlacement" data-xml="video/cp_IV_a_1.xml"/>

Очевидно, что самозакрывающиеся divs являются незаконными (по крайней мере, в одном контексте, когда я не могу выводить в качестве mime application/xhtml + xml, но я вынужден использовать mime text/html), и во всех остальных случаях они не проверяются.

4b9b3361

Ответ 1

Извините за поздний ответ, но вы знаете... это было Рождество.: 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 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>

С Рождеством! ^ _ ^

Ответ 2

Источники:

  • http://fr.php.net/manual/en/class.domdocument.php#domdocument.props.documentelement
  • http://fr.php.net/manual/en/domdocument.savexml.php
  • http://stackoverflow.com/info/23622858/how-to-write-xml-self-closing-tag-using-domdocument
<?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);