用于获取节点并排除其中的节点的 XPath 表达式

XPath expression to get a node and exclude a node within

我正在尝试让 div "entry" 接受带有 class = "metadata"

的段落标记中的所有内容
<div class="entry">
    <p>The senator's lack of action on gun legislation is glaring after
       two mass shootings this weekend killed 31.</p>
    <p>McConnell has for months now been the plug halting nearly every piece 
       of legislation Democrats pass through the House, including gun 
       measures that enjoy bipartisan support.</p>
    <p class="metadata alt">
        <small>
            This entry was posted on Tuesday, August 6th, 2019 at 10:23 am
        </small>
    </p>
</div>

如果我理解正确你在寻找什么,表达式

//div[@class='entry']/p[position() = 1 to count(../p[not(@class="metadata alt")])]

选择

The senator's lack of action on gun legislation is glaring after two mass shootings this weekend killed 31.The senator's lack of action on gun legislation is glaring after two mass shootings this weekend killed 31. McConnell has for months now been the plug halting nearly every piece of legislation Democrats pass through the House, including gun measures that enjoy bipartisan support.

此 XPath 选择 div 下 class entry.

下的任何内容

然后使用 /*[not(@class="metadata alt") 查看所有 class 值为 "metadata alt" 的子节点,其中包括没有 class 属性的节点...

//div[@class="entry"]/*[not(@class="metadata alt")]

这给出了两个元素...

<p>The senator's lack of action on gun legislation is glaring after
       two mass shootings this weekend killed 31.</p>
<p>McConnell has for months now been the plug halting nearly every piece 
       of legislation Democrats pass through the House, including gun 
       measures that enjoy bipartisan support.</p>

如果要检查class属性是否包含metadata,来自How can I match on an attribute that contains a certain string? ...

//div[@class="entry"]/*[not(contains(concat(' ', @class, ' '), ' metadata '))]

要测试的完整代码是...

$html = '<div class="entry">
    <p>The senator\'s lack of action on gun legislation is glaring after
       two mass shootings this weekend killed 31.</p>
    <p>McConnell has for months now been the plug halting nearly every piece 
       of legislation Democrats pass through the House, including gun 
       measures that enjoy bipartisan support.</p>
    <p class="metadata alt">
        <small>
            This entry was posted on Tuesday, August 6th, 2019 at 10:23 am
        </small>
    </p>
</div>';

$doc = new DOMDocument();
$doc->loadHTML($html);

$xp = new DOMXPath($doc);

$p = $xp->query('//div[@class="entry"]/*[not(@class="metadata alt")]');
foreach ($p as $out )   {
    echo $doc->saveHTML($out).PHP_EOL;
}