PHP DOM - 解析包含某些HTML标记的文本节点

时间:2011-12-05 12:38:57

标签: php html parsing dom nodes

我最近收到了解析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>等),以便在新的翻译文件中将完整的句子保持在一起 - 并保持标记大致完整。

2 个答案:

答案 0 :(得分:0)

考虑在“查看标签”上使用strip_tags,并在要实际拆分的标签上使用允许标签的第二个参数。

答案 1 :(得分:0)

如果您有一个节点并希望将其标准化为纯文本:

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

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

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

如果您的要求比这更复杂,那么最好使用带有身份转换的XSL来生成更符合您自己喜欢的新DOM树。例如,如果您有一些您想要的顶级节点(如<p>),并且想要删除一些但不是所有子节点(例如,“保持emstrong ,但是向上折叠cite,那么DOM解决方案将非常繁琐。