PHP xpath - find element with a value and also get elements before and after element
Use this:
$project = $xml_object->xpath("//photo[filename='$image_id']");
XPath how to query the next node
Since League with id = 20 is halfway through the XML file you can do it dynamically using XPath. Here's a simple PHP code snippet:
<?php
$xml = <<<XML
<Leagues>
<League>
<Id>20</Id>
<Name>Major League Soccer</Name>
<Country>USA</Country>
<Historical_Data>Partial</Historical_Data>
<Fixtures>Yes</Fixtures>
<Livescore>Yes</Livescore>
<NumberOfMatches>135</NumberOfMatches>
<LatestMatch>2013-06-16T04:00:00+02:00</LatestMatch>
</League>
<League>
<Id>33</Id>
<Name>Allsvenskan</Name>
<Country>Sweden</Country>
<Historical_Data>Partial</Historical_Data>
<Fixtures>Yes</Fixtures>
<Livescore>Yes</Livescore>
<NumberOfMatches>88</NumberOfMatches>
<LatestMatch>2013-06-15T16:00:00+02:00</LatestMatch>
</League>
</Leagues>
XML;
$sxe = new SimpleXMLElement($xml);
// Retrieve league with Id = 20
$league20 = $sxe->xpath("//League[Id='20']");
print_r($league20);
// Retrieve league right after the one with Id = 20
$leagueAfter20 = $sxe->xpath("//League[Id='20']/following-sibling::League[1]");
print_r($leagueAfter20);
Output
Array
(
[0] => SimpleXMLElement Object
(
[Id] => 20
[Name] => Major League Soccer
[Country] => USA
[Historical_Data] => Partial
[Fixtures] => Yes
[Livescore] => Yes
[NumberOfMatches] => 135
[LatestMatch] => 2013-06-16T04:00:00+02:00
)
)
Array
(
[0] => SimpleXMLElement Object
(
[Id] => 33
[Name] => Allsvenskan
[Country] => Sweden
[Historical_Data] => Partial
[Fixtures] => Yes
[Livescore] => Yes
[NumberOfMatches] => 88
[LatestMatch] => 2013-06-15T16:00:00+02:00
)
)
php - xpath select element and then select children
The second param to the query
is a $contextnode
that way you can use relative XPath like this:
foreach ($articles as $article) {
$href = $xpath->query('./a/@href', $article)->item(0)->nodeValue;
# $href = $xpath->evaluate('string(./a/@href)', $article); # using evaluate
}
How to select the text() immediately following an element conditionally in XPath?
You can achieve this with the following:
<?php
$xmldoc = new DOMDocument();
$xmldoc->loadXML(<<<XML
<span id="outer">
<div style="color:blue">51</div>
<span class="main">Gill</span>$500
<span style="color:red">11</span>
<span></span>James
<div style="color:red">158</div>
<div class="sub">Mary</div>
</span>
XML
);
$xpath = new Domxpath($xmldoc);
$nodes = $xpath->query("//span[@id='outer']/*");
$str_out = "";
foreach ($nodes as $node)
{
if ($node->hasAttribute('class'))
{
if ($node->getAttribute('class') == "main")
$str_out .= $node->nodeValue . " ";
}
else if ($node->hasAttribute('style'))
{
$node_style = $node->getAttribute('style');
preg_match('~color:(.*)~', $node_style, $temp);
if ($temp[1] == "blue")
$str_out .= $node->nodeValue . " ";
}
// Now evaluate if the IMMEDIATELY next sibling is text()
$next_node = $xpath->query('./following-sibling::node()[1]/self::text()[normalize-space()]', $node);
if ($next_node->length)
{
$str_out .= trim($next_node->item(0)->nodeValue) . " ";
}
}
echo $str_out;
The XPath query:
./following-sibling::node()[1]/self::text()[normalize-space()]
says:
.
from the context nodefollowing-sibling::node()[1]
take the first following sibling node (whether it be a text node or an element (or even a comment))self::text()[normalize-space()]
take the "current" node if it is a text node and doesn't consist of only whitespace
Output is:
51 Gill $500 James
This will also handle the scenario where you could have a text node after the last child element of the parent <span id="outer">
.
Xpath - select element with attribute and take another attribute value
Thought the issue is resolved, I just want to provide the idea how you can quickly check your xpath here.
This will give you the message if xpath is not correct and you can get idea what's wrong.
PHP Xpath: Get node value by class name
har07's answer was on the right track, but it only returned the node list with length set to 3 like I was already receiving with my existing code.
Original code:
$productPrice = $productRaw[1]->getElementsByTagName('li');
har07's suggestion:
$productPrice = $xpath->query('.//li[contains(@class, "itemtwo")]', $productRaw->item(1));
Solution, which returns the node value where an elements class name is equal to itemtwo
:
$productPrice = $xpath->query('.//li[contains(@class, \'itemtwo\')]', $productRaw[1])->item(1)->nodeValue;
selecting first 6 element with xpath [position() = 6]
i think you need this.
$route = $path->query("//li[1]/img[@class='lazy' and position() <= 6]");
foreach($route as $val){
var_dump(trim($val->getAttribute("data-original")));
}
if you don't want to specify the index of your <li>
you need to use a counter.
$route = $path->query("//li/img[@class='lazy' and position() <= 6]");
$ctr = 0;
foreach($route as $val){
if ($ctr <= 6){
var_dump(trim($val->getAttribute("data-original")));
}
$ctr = $ctr + 1;
}
How to get the next HTML element after a comment by XPath?
You could alter your XPath expression to use the following-sibling
axis and say pick up the first node after the comment...
$comments = $xpath->query('//comment()/following-sibling::*[1]');
If you need the comment and the next node, you can first get the comment and then use XPath relative to that comment to fetch the following node...
$comments = $xpath->query('//comment()');
foreach ($comments as $comment)
{
echo $comment->nodeValue.PHP_EOL;
$next = $xpath->query("following-sibling::*[1]", $comment)[0];
echo $next->nodeValue.PHP_EOL;
}
Related Topics
Set Quantity Minimum, Maximum and Step at Product Level in Woocommerce
Change "Billing Details" Text to "Shipping Details" on Woocommerce Checkout Page
How to Avoid Using PHP Global Objects
Does PHP Feature Short Hand Syntax for Objects
How to Curry Method Calls in PHP
How to Use MySQLi Bind_Param Dynamically
How to Safely Store a Password Inside PHP Code
How to Create a Nested Array Out of an Array in PHP
.Htaccess for Friendly Url with Multiple Variables
PHP Undefined Variable in a Closure
How to Check If Value Already Exists in MySQL Database
Set Multiple='False' in a Form in a Many to Many Relation Symfony2
How to Destroy Session with Browser Closing in Codeigniter
Difference(When Being Applied to My Code) Between Int(10) and Int(12)
Ip Address Is Showing in Form Action with Codeigniter Http://::1/Codeigniter/ in HTML Sourcecode