首页 > 解决方案 > 复杂的 Xpath 获取除某些特定类属性之外的所有值

问题描述

我有一个标记 HTML,如下所示:

<body>
    <div>......</div>
    ............
    <div class="entry-content">
        <div class="code1 code2">(ads.....);</div>
        <p><img src="https://www..."></img></p>
        <h2> title </h2>
        <div class="code1-block code2">(ads.....);</div>
        <div class="data1 dta-ta1">
              <ul><li><p> text</p></li>
                  <li><span> text2 </span></li>
                  <li><span> text3 </span></li>
                  <div class="codex1 code-block"><span>(ads ....); </span></div>
                  <li><span> text4 </span></li>
                  <div class="codex1 code-block"><span>(ads ....); </span></div>
              </ul>
        </div> 
        <div class="codex2-block code2">(ads.....);</div>
        <div class="data2-entry dta-ta2">
              <p>
                <span> text5</span>
              </p>
              <p> text6 </p>
              <p> text7 </p
              <div class="codex1 code-block"><span>(ads ....); </span></div>
              <li><span> text8 </span></li>
              <div class="codex1 code-block"><span>(ads ....); </span></div>
        </div>
  </div>
</body>

我试图“进入 div 并class="entry-content"从其子节点获取所有文本,不包括子节点class= "code1", "code2", "codex1", "codex2"

我的代码如下所示只是转到 div 并从子节点获取所有文本。但是,我无法使用 code1 和 code2 从子节点中删除文本。感谢您的支持。谢谢。

 $classname='entry-content';
 $a = new DOMXPath($dom);
 $query = "//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]";

 $list = $a->query($query);

 if ($list->length > 0) {
    foreach ($list as $element) {
        $nodes = $element->childNodes;

          foreach ($element as $node) {
             $bodytext = trim(preg_replace('/[\r\n]+/', ' ', $node->nodeValue));
             $bodyContent .= '<p>' . $bodytext . '</p>';
          }
    }
 }

我的预期输出:

https://www ...

标题

文本2

文本3

文本4

文本5

文本6

文本7

文本8

标签: phphtmlxmlxpath

解决方案


您的输入文档格式不正确,>缺少a </p,并且div未正确关闭。输入文档固定后,工作路径表达式为

XPath 表达式

//div[@class='content']//text()[not(ancestor::div/@class[contains(., 'code')])][normalize-space()]

它选择所有文本节点,但前提是它们没有祖先div元素class的值包含“代码”的属性,并且选择的文本节点不能是纯空格。

输出

单个结果由 分隔------

 title 
-----------------------
 text
-----------------------
 text2 
-----------------------
 text3 
-----------------------
 text4 
-----------------------
 text5
-----------------------
 text6 
-----------------------
 text7 
-----------------------
 text8 

更新

我试过你的回答。它可以工作,但是我仍然需要来自 img 标签的来源。我怎么才能得到它?

也可以选择元素的source属性img,但这会使 Xpath 表达式更加复杂。您应该只添加另一行 PHP 来评估单独的路径表达式,例如:

//div[@class='entry-content']/p/img/@source

更新 2

虽然我绝对不建议使用这个表达式(因为它会混淆你的代码),但这里是如何使用联合运算符将两个表达式组合成一个表达式:

//div[@class='entry-content']//text()[not(ancestor::div/@class[contains(., 'code')])][normalize-space()] | //div[@class='entry-content']//p/img/@src

推荐阅读