PHP XPath 获取属性值的一部分

PHP XPath to get a part of an attribute value

我必须解析一个显示通话清单的 HTML 网站。转换为 XML 后,结构为:

<body>
    <form name="mainform" method="POST" action="baz" class="all">
        <input type="submit" value="" style="position:absolute;top:-9999px;left:-9999px;" name="apply"/>
        <p>foo</p>
        <div class="bar">
            ..
        </div>
        <br/>
        <div class="onPageTabsBox">
            <ul class="tabs onPageTabs">
                ...
            </ul>
        </div>
        <table id="baz">
            <tr class="thead">
                ...
            </tr>
        </table>
        <div id="uiScroll">
            <table id="bla">
                <tr class="showif_in">
                    ...
                </tr>
                ...    
                <tr class="showif_out">
                    <td class="call_out" title="outbound call" datalabel="29.12.19 11:13"/>
                    <td>29.12.19 11:13</td>
                    <td title="Doe, John (privat) = 0123456789" datalabel="Name / Rufnummer">
                        <a href=" " onclick="return onDial('0123456789');">Doe, John (privat)</a>
                    </td>
                    <td datalabel="foo">bar</td>
                    <td title="987654 (Internet)" datalabel="own number">987654</td>
                    <td class="duration" data-timestr="0:02" datalabel="duration">2 Min</td>
                    <td class="btncolumn">
                        ...                        
                    </td>
                </tr>
                <tr class="showif_out">
                    ...
                </tr>

我需要的功能是从来电、去电...中获取 phone 号码。 所以我尝试从 td 节点获取 phone 数字,其中 title 包含 " = " 目前功能是这样的:

function getCallList($config, string $type = '')
{
    ...
    $xmlSite = convertHTMLtoXML($response);
    switch ($type) {
        case 'in':
        case 'out':
        case 'fail':
        case 'rejected':
            $query = sprintf('//form/div/table/tr[@class="showif_%s"]', $type);
            break;
        default:                                   // get all recorded calls
            $query = '//form/div/table/tr';
    }
    $rows = $xmlSite->xpath($query);
    foreach ($rows as $row) {
        $numbers = $row->xpath('substring-after(//td[@title], " = ")');
    }
    ...
}

在这里咨询了类似的问题后,我尝试了 $numbers = $row->evaluate('substring-after(//td[@title], " = ")'); 和其他几个 xPath 表达式 - 不幸的是我无法获取子字符串。除此之外,我怀疑只需要一个查询就可以得到一个包含 phone 个数字的数组。

如前所述 here and ,很遗憾,您无法使用 XPath 1.0 在一次查询中完成此操作。

您可以做的是列出属于这些 <td> 的所有 title 属性,然后使用 preg_match 获取 = 之后的所有内容空格:

$rowTitleAttrs = $xmlSite->xpath('//tr[@class="showif_out"]/td/@title');

$phoneNumbers = [];
foreach ($rowTitleAttrs as $rowTitleAttr) {
  if (preg_match('/(?<= = )(?<phoneNumber>.*?)$/', $rowTitleAttr->title, $matches)) {
    $phoneNumbers[] = $matches['phoneNumber'];
  }
}

我在此过程中冒昧地简化了您的 XPath 查询,因为 class 名称 应该 足够准确,不必说明通向的整个路径它。

演示:https://3v4l.org/1oqqA