将HTML导入DOMDocument或SimpleXML时删除内联元素?

时间:2010-01-17 08:13:42

标签: php html parsing simplexml domdocument

我有一个外部HTML源代码,我想要将其转换为本地XML文件或添加到MySQL数据库。

外部源主要是规范化的,并且(有些)是语义的,因此我需要做的就是使用XPATH来获取所有td内容或所有li内容等。问题是这些项目偶尔使用<strong><b><i>标记来设置我需要的元素的样式。

这在技术上是语义的,因为关键是要强调特定文本,开发人员可能希望使用不是浏览器默认值的CSS。

问题是我尝试抓取的实际内容被视为此内联元素的子项,因此像simplexmlDOMDocumentDOMNode这样的PHP扩展会将它们视为此类内容。例如:

<table>
<tr><td>Thing 1</td><td>Thing 2</td></tr>
<tr><td>Thing 3</td><td>Thing 4</td></tr>
<tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
</table>

将导致:

 [table] =>
    [tr] =>
        [td] => Thing 1
        [td] => Thing 2
    [tr] =>
        [td] => Thing 3
        [td] => Thing 4
    [tr] =>
        [td] => 
            [strong] => Thing 5
        [td] => 
            [strong] => Thing 6

显然上面并不是simplexml返回的内容,但上面反映了一般问题。

有没有办法,使用已经内置到DOMDocument中的参数或使用额外复杂的XPath查询来获取td元素的内容,其中任何子元素(如果有的话)都被剥夺了它们的后代状态并将所有内容视为查询元素的文本?

目前,我所拥有的唯一解决方案是:

a)有一个foreach循环检查每个结果,如:

$result_text = ($result -> strong) ? $result - strong : $result;

b)使用正则表达式从HTML字符串中删除任何<strong>标记,然后将其导入任何预构建的类,如simplexml或DOMDocument。

3 个答案:

答案 0 :(得分:1)

在使用正则表达式解析html之前,请先阅读this的第一个答案,如果只是为了娱乐。 XPath就是答案,获取td的文本而不是继续解析它。因此,您只需搜索//td之类的内容并完整地获取结果(而不是继续构建树,以便您拥有强大的树叶或其他任何东西。

答案 1 :(得分:1)

您不能只使用strip_tags()删除额外标记吗?

$table = simplexml_load_string(
    '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>'
);

foreach ($table->xpath('//td') as $td)
{
    $content = strip_tags($td->asXML());
    echo $content, "\n";
}

答案 2 :(得分:0)

如果你正在使用DOMDocument,那么一旦你选择了一个DOMNode,属性textContent应该只包含它的文本部分而且它只是所有的孩子...... 完全你是什么的要求。

$table = '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>';

$dom = new DOMDocument;
$dom->loadHTML($table);
$xpath = new DOMXPath($dom);

$els = $xpath->query('//td');
echo $els->item(4)->textContent; //Thing 5

或者,根据节点的类型,您也可以检查nodeValue。我不记得确切的区别,但textContent就是你想要的。