simplexml_import_dom在最后一个节点后丢失文本

时间:2014-01-03 11:07:01

标签: php simplexml domdocument

我的HTML来自WYSIWYG编辑器,所以我无法控制它附带的HTML。我需要解析才能创建PDF。

我创建了一个DomDocument并加载HTML并将其传递给simpleXML,因为它更容易处理。 但是我偶尔会松开Text,因为它是在最后一个HTML元素之后设置的。

// text to import
$text = "Text beginnning<strong>Lorem ipsum dolor sit amet, consetetur</strong>
        Lorem ipsum dolor sit amet, consetetur.<br \/><br \/><strong>Lorem ipsum 
        dolor sit amet, consetetur</strong><ul><li>Lorem ipsum dolor sit amet, consetetur
        <\/li><li>Lorem ipsum dolor sit amet, consetetur<\/li><li>Lorem ipsum 
        dolor sit amet, consetetur<\/li><li>Lorem ipsum dolor sit amet, consetetur
        <\/li><\/ul>Text after last node";

// Load text in dom and pass it to simplexml
$dom = new DOMDocument();
$dom->loadHTML($text);
$dom->recover = true;
if ($dom) {
    $sxml = simplexml_import_dom($dom);
    unset($dom);
    if ($sxml) {
        $this->parseHtmlContent($sxml->children());
    }
}

所以“最后一个节点之后的文字”在途中迷路了,我不知道该怎么办?

如何防止这种情况发生?

3 个答案:

答案 0 :(得分:1)

SimpleXML没有任何文本节点的表示,或者除了元素和属性之外的任何其他表示。您可以使用字符串强制转换((string)$simplexml_object)获取元素(或属性)的完整字符串内容,但这很少是您在HTML上下文中实际需要的内容 - 请考虑这个简单的HTML:

<p>some text with <em>an emphasised part</em> in the middle of it</p>

由SimpleXML提供的<p>元素的“文本内容”为"some text with in the middle of it" - "an emphasised part"<em>元素的文本内容。

当元素具有 子节点文本内容,而不是两者的混合时,SimpleXML的文本处理才真正有意义。对于XML作为数据序列化,这是有道理的 - 包含文本值的元素的分层文档很容易以这种方式处理 - 但对于文本标记语言,它实际上是“被设计破坏”。

如果您可以保证文档的某些部分将包含特定的HTML结构(例如示例中的<ul> / <li>序列),那么您可以使用SimpleXML来解析该部分。 <{1}}的任何一侧的内容都可以使用DOM恢复并添加回输出中。

答案 1 :(得分:0)

最后一个节点之后的文本与该节点位于同一级别。结构是:

    object(SimpleXMLElement)#2 (1) {
      ["body"]=>
      object(SimpleXMLElement)#3 (2) {
        ["p"]=>
        string(63) "Text beginnning
            Lorem ipsum dolor sit amet, consetetur."
        ["ul"]=>
        object(SimpleXMLElement)#4 (1) {
          ["li"]=>
          array(4) {
            [0]=>
            string(47) "Lorem ipsum dolor sit amet, consetetur
            "
            [1]=>
            string(38) "Lorem ipsum dolor sit amet, consetetur"
            [2]=>
            string(46) "Lorem ipsum
            dolor sit amet, consetetur"
            [3]=>
            string(47) "Lorem ipsum dolor sit amet, consetetur
            "
          }
        }
      }
    }

因此,body节点包含其他节点以及字符串。要获取body节点下的字符串,您必须调用__toString方法:

$text = "Text beginnning<strong>Lorem ipsum dolor sit amet, consetetur</strong>
        Lorem ipsum dolor sit amet, consetetur.<br \/><br \/><strong>Lorem ipsum
        dolor sit amet, consetetur</strong><ul><li>Lorem ipsum dolor sit amet, consetetur
        <\/li><li>Lorem ipsum dolor sit amet, consetetur<\/li><li>Lorem ipsum
        dolor sit amet, consetetur<\/li><li>Lorem ipsum dolor sit amet, consetetur
        <\/li><\/ul>Text after last node";

$text = stripcslashes($text);

// Load text in dom and pass it to simplexml
$dom = new DOMDocument();
$dom->loadHTML($text);
$dom->recover = true;

if ($dom) {
    $sxml = simplexml_import_dom($dom);
    unset($dom);
    if ($sxml) {
        var_dump((string) $sxml->body);
    }
}

有关进一步的信息,请查看:

答案 2 :(得分:0)

确保整个内容包含在一个包含元素中:

$dom->loadHTML('<div>' . $text . '</div>');