1

There's the sum-function in xpath:

<list>
    <a>1</a>
    <a>3</a>
    <a>4</a>
</list>

Now with SimpleXml...

var_dump($xml->xpath("sum(/list/a)"));

delivers NULL instead of 8

What's wrong here?

see it not working: https://eval.in/135558

EDIT: I've used this workaround for SimpleXml to avoid iterating:

$sum = $xml->xpath("/list/a"); 
$sum = array_sum(array_walk("intval", $sum));
michi
  • 6,565
  • 4
  • 33
  • 56

2 Answers2

3

If you're using SimpleXML, you're going to have to do it manually. However, you can use DOMDocument to achieve this. Just use evaluate() method to evaluate the XPath expression:

$dom = new DOMDocument;
$dom->loadXML($xml); // $xml is the XML string

$xpath = new DOMXPath($dom);
$sum = (int) $xpath->evaluate('sum(/list/a)'); // => 8

Demo


SimpleXML solution:

$xml = simplexml_load_string($xml);
$sum = 0;

foreach ($xml->a as $node) {
    $sum += (int) $node;
}

echo $sum; // => 8

Demo

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
  • I didn't know before that there is really no way to achieve this with simplexml (because I never tried that). +1 for stating that and another reason to use the `DOM` extension consequently :) – hek2mgl Apr 11 '14 at 17:55
  • @AmalMurali for `SimpleXml`, I found `$sum = $xml->xpath("/list/a"); $sum = array_sum(array_walk("intval", $sum));` – michi Apr 11 '14 at 21:58
  • @AmalMurali This is definitely a limit of `SimpleXml`. Usually, I prefer `SimpleXml` a lot over `DOM` for its, well, simplicity. – michi Apr 11 '14 at 22:01
1

Use DOMXPath::evaluate() here:

$str = <<<XML
<list>
    <a>1</a>
    <a>3</a>
    <a>4</a>
</list>
XML;

$output = new SimpleXMLElement($str);
$doc = new DOMDocument();
$doc->loadXML($str);

$selector = new DOMXPath($doc);

var_dump($selector->evaluate('sum(//list/a/text())'));
// double(8)

Side-note: It will return a double not an integer. This might be surprising in the first place.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266