user633440
user633440

Reputation:

XPath expression to get a node and exclude a node within

I'm trying to get everything inside the div "entry" accept for the paragraph tag with the 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>

Upvotes: 0

Views: 55

Answers (2)

Nigel Ren
Nigel Ren

Reputation: 57121

This XPath selects anything under your div with class entry.

Then uses /*[not(@class="metadata alt") which looks at all child nodes that do not have a class value of "metadata alt", which includes nodes which do not have a class attribute...

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

This gives two elements...

<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>

If you want to check if the class attribute contains metadata, from How can I match on an attribute that contains a certain string? ...

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

The full code to test is...

$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;
}

Upvotes: 1

Jack Fleeting
Jack Fleeting

Reputation: 24930

If I understand correctly what your are looking for, the expression

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

selects

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.

Upvotes: 0

Related Questions