用php写后端动态生成网页内容的时候,用到了DOMDocument类的操作。为了减少创建元素和文本节点的代码(与效率无关),使用了loadXML()方法载入静态的HTML文本(通过heredoc)。
$xml = new DOMDocument(); $xml->loadXML(<<<_HTML <div class="-article"> <div class="-article-title" onselectstart="return false;"></div> <hr/> <div class="-article-body"></div> <hr/> <div class="-article-extra"></div> <div class="-aborted"></div> <div class="-article-picture"></div> </div> _HTML ); ...... echo xml->saveXML();
没错,就是用loadXML()载入HTML,这样做是因为saveHTML()的时候会输出完整的HTML文档(包含html和body元素)而不是我想要的文章部分,而saveXML()则只需要去除首行的文档声明即可。
这里不谈这样的做法好与不好,只说说我遇到的问题。
遇到的问题是,网页版面乱了。出现了块级元素的堆叠,就是生成的元素后面的同级元素变成了它的子元素。感觉是标签没有闭合导致的,用浏览器看了生成的网页代码,终于找到了问题所在。
耗子屎在这一行:
<div class="-aborted"></div>
由于一些原因,生成元素中这块被废弃了,后面的代码又很多地方使用了getElementsByTagName方法获取指定元素,需要靠子元素的位置定位,所以不好直接删除(可见装载静态的html文档结构并不是个好点子),于是把这个<div>的类名设置为-aborted,然后统一处理。因为是废弃元素,所以自然也不会为它生成内容了,最后saveXML输出的文本中,将这个空元素<div class="-aborted"></div>转化成了<div class="-aborted"/>。在html5中自闭合标签是有严格控制的,只有特定的标签才允许,因此<div/>并没有被浏览器认为是一个闭合的标签,然后和后面的div块混乱了,才导致的这个问题。
解决办法是,给heredoc中的废弃元素的内容加个空格,xml封装器就不会将它当作空元素了。不过最好还是全都动态生成元素,少生幺蛾子。或者使用其他更好的办法。