空节点的非法自闭节点表示法 - 使用PHP DOMDocument输出XHTML

时间:2015-12-02 03:09:16

标签: php xml validation xpath xhtml

我正在使用PHP中的XPATH处理XML兼容的XHTML输入,如下所示:

$xml=new DOMDocument();
$xml->loadXML(utf8_encode($temp));
[...]
$temp=utf8_decode($xml->saveXML());

出现的问题是根据HTML5规范可能无法自行关闭的节点,例如

<textarea id="something"></textarea>

或由JS利用的div

<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);

编辑:我真的遇到了愚蠢的搜索和替换的麻烦,我不打算用RegExp攻击输出XHTML。考虑这个例子:

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

显然,自我关闭的div是非法的(至少在我无法输出mime application / xhtml + xml但我被迫使用mime text / html的上下文中),在所有其他情况下,他们肯定不会验证。< / p>

2 个答案:

答案 0 :(得分:4)

很抱歉迟到的回复,但你知道......那是圣诞节。 :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>

圣诞快乐! ^ _ ^

答案 1 :(得分:3)

来源:

  • http://fr.php.net/manual/en/class.domdocument.php#domdocument.props.documentelement
  • http://fr.php.net/manual/en/domdocument.savexml.php
  • http://stackoverflow.com/questions/23622858/how-to-write-xml-self-closing-tag-using-domdocument
<ul id="listview"></ul>
<script type="text/template" id="item">
  <li><%= author %></li>
</script>