0

这是我的 xPath,但是我看到 | 运算符只计算 2? 我怎样才能使它超过两个?我在下面发布了我的代码

function extractNodeValue($query, $xPath, $attribute = null) {
    $node = $xPath->query("//{$query}")->item(0);
    if (!$node) {
        return null;
    }
    return $attribute ? $node->getAttribute($attribute) : $node->nodeValue;
}


$document = new DOMDocument();
$document->loadHTMLfile(${'html'.$i});
$xPath = new DOMXpath($document);

    $tel = extractNodeValue('//*[@id="eventDetailInfo"]/div[3]/div[4] | //*[@id="eventDetailInfo"]/div[3]/div[3] | //*[@id="eventDetailInfo"]/div[3]/div[5]',$xPath);
4

4 回答 4

3

当你写2+2+2时,+是一个二元运算符;你的表情意味着(2+2)+2

同样|在 XPath 中是一个二元运算符,但由于结果与操作数的类型相同,它以相同的方式与自身组合:$x|$y|$z表示($x|$y)|$z

于 2013-06-25T07:16:08.487 回答
0

似乎您的问题以某种方式导致了错误的方向。
xpaht 没有任何问题。正如这里已经指出的那样,xpath 查询可以找到的节点数量|不受限制。

但是您->item(0);在 extractNodeValue() 中使用它只会查看第一项。

如果您想输出所有找到的节点的“值”,请尝试以下操作:

function extractNodeValue($node, $attribute = null) {

    if (!$node) {
        return null;
    }
    return $attribute ? $node->getAttribute($attribute) : $node->nodeValue;
}

$document = new DOMDocument();
$document->loadHTML(${'html'.$i});
$xPath = new DOMXpath($document);

$nodes = $xPath->query('//a | //b | //c');
foreach($nodes as $n) {
    $tel = extractNodeValue($n);
    echo $tel;
}

如果这不起作用,则很可能您的 html 页面与您的 xapth 表达式不匹配。

更新
查看评论中的 html 页面:要获取电话号码,请尝试以下操作:

$tel = extractNodeValue('//div[@id="eventDetailInfo"]//div[@class= "tel"]',$xPath);

返回:

string(15) "Phone: 22674608"
于 2013-07-03T09:54:40.697 回答
0

正如其他人已经指出的那样,您的电话查询将产生多个节点,但您的extractNodeValue函数只返回其中一个。我的建议是像这样重写它:

function extractNodeValue($query, $xPath, $attribute = null) {
  $values = array();
  foreach($xPath->query("//{$query}") as $node) {
    $values[] = $attribute ? $node->getAttribute($attribute) : $node->nodeValue;
  }
  return join($values, ", ");
}

这将返回单个逗号分隔字符串中的多个值,但更改分隔符很容易,或者如果这对您更有用,则将值作为数组返回。

我还建议去掉此处添加到查询中的“//”,并将其包含在调用代码中。否则,在某些情况下,您最终会被添加两次。但这并不是在这一点上修复的必要条件。

至于电话查询本身,您的查询取决于电话 div 处于某些固定位置,这根本不可靠(在某些页面上它也匹配网站和电子邮件地址)。

在我看来,您需要匹配两种不同的情况:在“Where”div(eventDetailInfo部分的 div 3)下和“Contact”div(div 4)下。

在 "Where" div 下,电话号码可以在不同的位置,但它们总是有一个 "tel" 类,所以最安全的查询可能是这样的:

//*[@id="eventDetailInfo"]/div[3]/*[@class="tel"] 

在“Contact” div 下,电话号码也可以在不同的位置,但在电话 div 上没有任何可以匹配的类。但是,该 div 中的内容始终以字符串“Phone:”开头,因此一种解决方案是使用 XPathstarts-with函数。

//*[@id="eventDetailInfo"]/div[4]/div[starts-with(.,"Phone:")]

然后,您可以将这两个查询与 union ( |) 运算符结合起来以涵盖这两种情况。或者(我认为这是一个更好的解决方案),您可以通过使其更通用来对这两种情况使用第二个查询,如下所示:

//*[@id="eventDetailInfo"]//div[starts-with(.,"Phone:")]                       

一个可能的缺点是这不再将搜索限制为“Where”和“Contact”div,因此如果eventDetailInfo部分的其他部分有电话号码,它也会匹配那些(尽管这可能是一件好事) .

请注意,即使没有联合,此查询仍会在某些页面上返回多个节点。extractNodeValue因此,无论哪种方式,如果要获取所有值,使用更新的函数至关重要。

于 2013-07-08T13:01:03.510 回答
0

您传递给extractNodeValue函数的 XPath 查询将导致//a | 乙 | c,它只会返回a节点,忽略bc节点。

可能你想运行//a | //b | //c获取第一次出现的 an或节点,对吗abc

如果是这种情况,您必须将使用$query参数的方式更改为以下内容:

<?php
$html = <<<HTML
<html>
    <div>
        <a>Empire Burlesque</a>
        <b>Bob Dylan</b>
        <i>USA</i>
    </div>
    <div>
        <a>Hide your heart</a>
        <b>Bonnie Tyler</b>
        <i>UK</i>
    </div>
</html>
HTML;

function extractNodeValue($query, $xPath, $attribute = null) {
    $node = $xPath->query($query)->item(0);
    if (!$node) {
        return null;
    }

    return $attribute ? $node->getAttribute($attribute) : $node->nodeValue;
}

$document = new DOMDocument();
$document->loadHTML($html);
$xPath = new DOMXpath($document);

$tel = extractNodeValue('//a | //b | //i', $xPath);
echo $tel;

输出:

Empire Burlesque
于 2013-07-02T22:04:11.153 回答