【问题标题】:Complex Xpath get all values excluding some specific class attributes复杂的 Xpath 获取除某些特定类属性之外的所有值
【发布时间】:2020-01-24 03:32:17
【问题描述】:

我有一个标记 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>

我尝试“使用class="entry-content" 进入div,从其子节点中获取所有文本,不包括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

【问题讨论】:

  • 你的预期输出是什么?
  • 我想从 class="content" 的子节点 insde div 中获取所有文本,并排除包含“code”类的子节点 EX:code1 code2, codex1, codex2 .... 有点复杂的 HTML 标记带来的挑战。我认为我们需要一个复杂的查询 xpath。
  • edit您的问题与预期的输出您提供的示例输入
  • 好的!我刚刚编辑过。

标签: php html xml xpath


【解决方案1】:

您的输入文档格式不正确,&lt;/p 缺少一个&gt;,并且一个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 标签的来源。我怎样才能得到它?

也可以选择img 元素的source 属性,但这会使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

【讨论】:

  • 感谢 Mathias 的回答。我用一个封闭的/ div修复了。我试过你的回答。它可以工作,但是我仍然需要来自 img 标签的来源。我怎样才能得到它?
  • @AnNguyen 我已经更新了我的答案来解决你的问题。
  • 如果能合二为一就好了。您修改后的答案完美无缺。我还测试了另一种获取源代码$tags = $dom-&gt;getElementsByTagName('p')-&gt;item(0)-&gt;getElementsByTagName('img'); foreach ($tags as $tag) { $featureImage = $tag-&gt;getAttribute('src'); } 的方法。然后它也可以工作。谢谢,马蒂亚斯。如果您只能将它组合在一行中,我将不胜感激!投票赞成你的答案。
  • @AnNguyen 再次更新了我的答案。请注意,您可能不应该使用这个表达式,因为它太复杂了。在 PHP 代码中计算两个表达式更有意义。
  • 是的,你是对的。搜索结果比分离部分花费的时间更长。我尝试将您的新代码用于 img 源,但没有成功。它返回空值。 $img_query = "//div[@class='entry-content']//p/img/@src"; $imglist = $a-&gt;query($img_query); foreach ($imglist as $imgitem) { $featureImage=$imgitem-&gt;nodeValue; } 。我不确定我的代码是否可以提取属性 src
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 2015-10-29
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多