使用PHP和xPath提取干净的文本表

时间:2014-03-08 11:56:21

标签: php xpath

我使用以下代码从HTML文件中提取值。代码返回一个文本块。我想知道如何改进代码并将此代码块的元素提取到干净的表中。

文件:

<div class=class1>
    <a href="">txt1</a>
            <div class=lvl2>
                    <p>hello1</p>
            </div>
    <a href="">txt2</a>
            <div class=lvl2>
                    <p>hello2</p>
            </div>
</div>

代码:

$doc = new DOMDocument();
@$doc->loadHTMLFile('file.htm');

$xpath = new DOMXPath($doc);

$list = $xpath->evaluate("//div[contains(@class, 'class1')]");

foreach ($list as $element)
    {
      echo '<p>' . $element->nodeValue . PHP_EOL . '</p>';
    }

期望的输出:

 txt1 | hello1
 txt2 | hello2

2 个答案:

答案 0 :(得分:1)

或者,如果你想确保单独输出每个表,你可以这样做。它假定维护了排序,我认为并不总是保证使用XML / XPath,但实际上它通常适用于大多数实现:

$doc = new DOMDocument();
$doc->loadHTMLFile('file.htm');

$xpath = new DOMXPath($doc);

$list = $xpath->evaluate("//div[contains(@class, 'class1')]");

foreach ($list as $element)
{
    $column1 = $xpath->query("//a", $element);
    $column2 = $xpath->query("//div/p", $element);

    for ($i = 0; $i < $column1->length; $i++) {
        echo $column1->item($i)->nodeValue . ' | ' . $column2->item($i)->nodeValue .  PHP_EOL;
    }
}

我已从@方法中删除loadHTMLFile错误抑制 - 我认为您不想使用它,因为如果失败,您将在以后遇到错误,并将其遗漏将使你的问题的原因更明确。

修正:如果你不想在两列上单独迭代,这是你可以构建循环的另一种方法。但是,如果每列中的行数在html中不匹配,它可能仍会失败:

foreach ($list as $element)
{
    $column1 = $xpath->query("//a", $element);

    for ($i = 0; $i < $column1->length; $i++) {
        $field1 = $column1->item($i);
        $field2 = $xpath->query("following-sibling::div", $field1)->item(0);

        echo $field1->nodeValue . ' | ' . trim($field2->nodeValue) .  PHP_EOL;
    }
}

答案 1 :(得分:0)

这个怎么样?:

$doc = new DOMDocument();
@$doc->loadHTMLFile('file.htm');

$xpath = new DOMXPath($doc);

$list = $xpath->evaluate("//div[contains(@class, 'class1')]/a");

foreach ($list as $element)
{
    $nextElement = $element->nextSibling;
    while ($nextElement->nodeType != XML_ELEMENT_NODE) {
        $nextElement = $nextElement->nextSibling;
    }

    echo $element->nodeValue . ' | ' . trim($nextElement->nodeValue) .  PHP_EOL;
}

我不太确定你为什么要<p>以及PHP_EOL,所以我把它们排除了,但你可以把它们放回你需要的地方。