【问题标题】:Parse HTML with PHP to get sibling elements grouped by class使用 PHP 解析 HTML 以获取按类分组的兄弟元素
【发布时间】:2011-11-07 20:45:06
【问题描述】:

我有一个巨大的 HTML 文档需要解析。 该文档是 <p> 元素的列表,所有(直接)body 标签的子元素。 区别在于类名。结构是这样的:

    <p class="first-level"></p>
    <p class="second-level"></p>
    <p class="third-level"></p>
    <p class="third-level"></p>
    <p class="nth-levels just-for-demo-1"></p>
    <p class="nth-levels just-for-demo-1"></p>
    <p class="third-level"></p>
    <p class="second-level"></p>
    <p class="third-level"></p>
    <p class="nth-levels just-for-demo-2"></p>
    <p class="first-level"></p>
    <p class="second-level"></p>
    <p class="second-level"></p>
    <p class="third-level"></p>

等等。 nth-level 可以是不是first-levelsecond-levelthird-level 的任何类名。 基本上,它是一个多层次的&lt;ul&gt; 元素,标记很差。

我想要做的是解析它并获取上述类名之一之间的所有&lt;p&gt; 元素(包括标签,而不仅仅是innerHTML)。

在上面的例子中,我想得到:

<p class="nth-levels just-for-demo-1"></p>
<p class="nth-levels just-for-demo-1"></p>

<p class="nth-levels just-for-demo-2"></p>

请问我该怎么做? 谢谢。

【问题讨论】:

    标签: php html-parsing


    【解决方案1】:

    使用 XPath:

    //p[not(@class='first-level')][not(@class='second-level')][not(@class='third-level')]
    

    要获取(非?)匹配的节点,则可以使用this answer获取节点的outerHTML。

    【讨论】:

    • 嗯,这很聪明,但是 XPath 不需要有效的 XML 吗?我正在查看的代码(太可怕了)是 HTML4 和无效的 XML。
    • 如果您可以通过 Tidy 或 Purifier 运行该“垃圾”,而其中大部分不会被视为癌变,那么您可以将其提供给 DOM 和 XPath。但否则,您将不得不使用其他东西。 DOM 对它接受的 html 非常挑剔。
    • 好主意,我会完成它并进行损坏评估。谢谢(现在我再次看到了这个名字)。
    【解决方案2】:

    您可以打开文件(使用 fopen 或类似的东西)并一次读取一行。然后只需检查所需的字符串是否在行中(例如使用 strstr),如果是,则将其添加到数组中或对行执行所需的操作。 注意:这仅适用于每个段落位于不同行的情况。

    fopen 文档

    strstr 文档

    【讨论】:

    • 谢谢。我不确定这些段落是否在一行上。我认为 HTML 解析器更适合这个。
    【解决方案3】:
    $doc = new DOMDocument;
    $doc->loadHTML(...);
    $query = '//p[contains(@class, "just-for-demo-")]';
    $xpath = new DOMXPath($doc);
    $entries = $xpath->query($query);
    
    foreach ($entries as $entry)
    {
      // not a best solution yet
      $attribute = '';
      foreach ($entry->attributes as $attr)
      {
        $attribute .= "{$attr->name}=\"{$attr->value}\"";
      }
    
      echo "<{$entry->nodeName}{$attribute}>{$entry->nodeValue}</{$entry->nodeName}>";
    }
    

    【讨论】:

    • 嘿,谢谢,但是just-for-demo- 是...好吧...只是为了演示...它不需要非常非常优雅。它只会运行一次。
    【解决方案4】:

    另外,如果你熟悉 jQuery,那么试试jQuery port to PHP,你可以拥有一套强大的工具来匹配文档中的一组元素(选择器),就像你过去使用 jQuery 和 Hierarchy 一样, 属性过滤器, 子过滤器等,Reference

    【讨论】:

    • 哈哈,现在有一个从任何事物到任何事物的端口。我认为这会很好。我试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多