PHP DOM -解析包含特定HTML标记的文本节点


PHP DOM - Parse text nodes that contain certain HTML tags

我最近得到了解析HTML文档中所有文本节点的帮助。结果代码如下:

$doc = new DOMDocument();
$doc->loadHTML($contents);
$doc->loadHTML("<p>not in the brackets..</p>");
$xpath = new DOMXPath($doc);
$textnodes = $xpath->evaluate('//text()');

使用以下摘录:

<p>This is a <b>nested <i>HTML</i> tag<b>...</p>

我可以创建一个元素数组:

Array
(
  [0] => This is a 
  [1] => nested
  [2] => HTML
  [3] => tag
  [4] => ...
)

我实际上想做的是检索所有文本节点,但允许某些HTML标记被"查看"。例如,我不希望<i>, <b><u>标记被解析为单独的节点;我宁愿将它们连接到前一个文本节点。理想情况下,上面的数组应该是这样的:

Array
(
  [0] => This is a nested HTML tag...
)
另一方面,<p>标签应被识别为单独的节点。所以下面的文本:
<p>paragraph 1 <b>here</b></p> <p>paragraph 2</b>

最好解析为:

Array
(
  [0] => paragraph 1 <b>here</b>
  [1] => paragraph 2

我已经阅读了一些关于XPath和PHP DOM的书籍,但老实说,我真的不知道如何去做。有人能给我指个正确的方向吗?谢谢你。

编辑

只是为了澄清输出必须是数组格式;我的目标是解析页面中的所有文本,以便在翻译文件中使用。因此,为了在新的翻译文件中保持完整的句子在一起,并保持标记大致完整,在解析的文本中需要某些HTML标记(<b>等)。

考虑在'已查看标记'上使用strip_tags,并在您想要实际分割的标记上使用第二个允许标记参数

如果您有一个节点,并希望将其规范化为纯文本:

XPATH: 'string(thenode)'
DOM:   $thenode->textContent;

这将忽略所有不是文本节点的子节点,并将其作为单个字符串返回。

因此,在您的示例中,像string(//p)这样的xpath将为您提供一个删除了所有元素的纯文本段落数组。您可以对DOM做同样的事情,使用getElementsByTagName()并为每个结果获取textContent属性。

如果您有比这更复杂的需求,那么最好使用带有标识转换的XSL来生成更符合您喜好的新DOM树。例如,如果您有一些想要的顶级节点(如<p>),并且希望剥离一些但不是所有的子节点(例如,"保留emstrong,但向上折叠cite),那么DOM解决方案将非常繁琐。