我最近得到了解析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>
),并且希望剥离一些但不是所有的子节点(例如,"保留em
和strong
,但向上折叠cite
),那么DOM解决方案将非常繁琐。