u01jmg3
u01jmg3

Reputation: 730

Using PHP and XPATH, how would you get the contents of the closest `h3`?

Upvotes: 2

Views: 655

Answers (2)

har07
har07

Reputation: 89295

You can try this XPath :

//h3[following-sibling::dl[1][.//span[contains(concat(' ', normalize-space(@class), ' '), ' home-side ') and span/img[@alt='Hull City']]]]

Basically, above XPath select <h3> element having next sibling <dl> element containing a <span class="home-side"> and another <span> with <img alt="Hull City"> (formatted version) :

//h3[
        following-sibling::dl[1][
                    .//span[
                        contains(concat(' ', normalize-space(@class), ' '), ' home-side ') 
                            and 
                        span/img[@alt='Hull City']
                    ]
        ]
    ]

UPDATE :

Following is an XPath example that checks for both home team and away team :

//h3[
        following-sibling::dl[1][
                    .//span[
                        contains(concat(' ', normalize-space(@class), ' '), ' home-side ') 
                            and 
                        span/img[@alt='Hull City']
                    ]
                        and
                    .//span[
                        contains(concat(' ', normalize-space(@class), ' '), ' away-side ') 
                            and 
                        span/img[@alt='Crystal Palace']
                    ]
        ]

    ]

UPDATE 2 :

To be able to account multiple <dl>s, I think it will be easier to find <dl> that satisfies home and away team criteria first, then move backward to find closest <h3> element from such <dl> :

//dl[
        .//span[
            contains(concat(' ', normalize-space(@class), ' '), ' home-side ') 
                and 
            span/img[@alt='Stoke City']
        ]
            and
        .//span[
            contains(concat(' ', normalize-space(@class), ' '), ' away-side ') 
                and 
            span/img[@alt='Crystal Palace']
        ]
    ]/preceding-sibling::h3[1]

Upvotes: 1

Kevin
Kevin

Reputation: 41875

If the structure is always going to be the same, you could point it first to that img tag with that alt value, then traverse it backwards.

Example:

$dom = new DOMDocument();
$dom->loadHTML($markup);
$xpath = new DOMXpath($dom);

$needle = 'Hull City';
$element = $xpath->query("//span/img[contains(@alt, '$needle')]");
if($element->length > 0) {
    $img = $element->item(0);
    $header = $xpath->query('ancestor::node()/preceding-sibling::h3[1]', $img);
    if($header->length > 0) {
        echo $header->item(0)->nodeValue; // Saturday 4 October
    }
}

Sample Output

Upvotes: 1

Related Questions