【问题标题】:Simplexml: parsing HTML leaves out nested elements inside an element with a text nodeSimplexml:解析 HTML 会在带有文本节点的元素中遗漏嵌套元素
【发布时间】:2015-03-08 15:08:40
【问题描述】:

我正在尝试解析一个特定的 html 文档,某种字典,大约有 10000 个单词和描述。 一切都很顺利,直到我注意到特定格式的条目没有得到很好的解析。

这是一个例子:

    <?php
    $html = '
        <p>
            <b>
                <span>zot; zotz </span>
            </b>
            <span>Nista; nula. Isto
                <b>zilch; zip.</b>
            </span>
        </p>
        ';

    $xml = simplexml_load_string($html);

    var_dump($xml);
    ?>

var_dump() 的结果是:

    object(SimpleXMLElement)#1 (2) {
      ["b"]=>
      object(SimpleXMLElement)#2 (1) {
        ["span"]=>
        string(10) "zot; zotz "
      }
      ["span"]=>
      string(39) "Nista; nula. Isto

            "
    }

如您所见 - Simplexml 将文本节点保留在标记内,但省略了子节点和文本。

我也试过了:

    $doc = new DOMDocument();
    $doc->loadHTML($html);
    $xml = simplexml_import_dom($doc);

结果相同。

在我看来,这是解析 html 时的常见问题,我尝试用谷歌搜索它,但唯一承认这个问题的地方是这个博客: https://hakre.wordpress.com/2013/07/09/simplexml-and-json-encode-in-php-part-i/ 但不提供任何解决方案。

关于在 SO 中解析 HTML 的帖子和答案过于笼统。

有没有简单的方法来解决这个问题? 或者,我应该改变我的策略吗?

【问题讨论】:

    标签: php xml parsing html-parsing simplexml


    【解决方案1】:

    您的观察是正确的:SimpleXML 在这里只提供子元素节点,而不提供子文本节点。解决方案是切换到 DOMDocument,因为它可以访问那里的所有节点、文本和元素子项。

    // first span element
    $span = dom_import_simplexml($xml->span);
    
    foreach ($span->childNodes as $child) {
        printf(" - %s : %s\n", get_class($child), $child->nodeValue );
    }
    

    此示例显示dom_import_simplexml 用于更具体的&lt;span&gt; 元素节点,并且遍历是在相应DOMElement 对象的子节点上完成的。

    输出:

     - DOMText : Nista; nula. Isto
    
     - DOMElement : zilch; zip.
     - DOMText : 
    

    第一个条目是&lt;span&gt; 元素中的第一个文本节点。其后是&lt;b&gt; 元素(同样包含一些文本),然后是另一个仅包含空格的文本节点。

    dom_import_simplexml 函数在 SimpleXMLElement 过于简单而无法在 XML 文档中进行更多差异化数据访问时特别有用。就像你在这里遇到的情况一样。

    完整示例:

    $html = <<<HTML
    <p>
        <b>
            <span>zot; zotz </span>
        </b>
        <span>Nista; nula. Isto
            <b>zilch; zip.</b>
        </span>
    </p>
    HTML;
    
    $xml = simplexml_load_string($html);
    
    // first span element
    $span = dom_import_simplexml($xml->span);
    
    foreach ($span->childNodes as $child) {
        printf(" - %s : %s\n", get_class($child), $child->nodeValue );
    }
    

    【讨论】:

    • 谢谢@hakre!你的答案是救命稻草。正是我想要的。另外,你有很好的博客link。对不起,我没有积分来投票给你。
    猜你喜欢
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多