使用 XPath 获取直接子级的文本

问题描述

我有这部分 HTML 需要解析:

<p>
    names: <strong><i>John</i>,<i>Mark</i></strong>
    <br>
    occupation: <strong>actor</strong>
    <br>
</p>

我正在使用 Symfony Dom Crawler 来解析几个页面。我需要 <p> 的直接子级的文本内容。使用我的例子,我想得到的结果是:

[
    'names:','John,Mark','occupation:','actor',]

我不知道要使用什么 XPath。我不认为我可以使用 CSS 选择器,因为它完全忽略了文本节点。这是我尝试过的:

$items = $crawler
    ->filter('p')
    ->filterXPath('//text()')
    ->extract(['_text']);

这显然是错误的,因为它需要所有文本节点,无论它们在哪里。我得到的结果是:

[
    'names:','John',','Mark','',]

如何获取直接子级的文本内容

编辑

我设法通过 //p/text()|//p/* 选择器获得了我需要的东西,但我仍在寻找优化版本,其中:

  1. 未明确使用父选择器 p,因为在我的真实示例中,父选择器更复杂。我不明白为什么 /text()|/* 不起作用。
  2. 如果可能,最好跳过选择器中的 <br>。我目前只是在提取后过滤掉空文本内容

解决方法

我不知道那个库,也没有 PHP 或那个库来测试,但通读 https://symfony.com/doc/current/components/dom_crawler.html#expression-evaluation 对我来说听起来好像你想要,例如

$crawler
->filter('p')
->filterXPath('p/node()')
->evaluate('normalize-space()')

应该选择 p 元素,然后选择 p 元素的任何子节点,然后返回任何这些子节点的规范化字符串值。

根据空格的处理方式,可能需要使用 ->filterXPath('p/node()') 以避免返回的其他文本字符串之间出现空字符串。