Using PHP, I would like to write a function that takes numbers from XML, and multiplies those numbers. However, I don't know how to work with decimal numbers in SimpleXML.
PHP
$xml = new SimpleXMLElement(
'<DOM>
<TAB id="ID1" width="30.1" height="0.5" ></TAB>
<TAB id="ID2" width="15.7" height="1.8" ></TAB>
</DOM>');
foreach ($xml->children() as $second_level) {
echo $second_level->attributes()->id."<br>";
echo ($second_level->attributes()->width * 10)."<br>";
echo ($second_level->attributes()->height * 10)."<br>";
}
The current (wrong) output:
ID1
300
0
ID2
150
10
The correct output should be:
ID1
301
5
ID2
157
18
The other answers are on the right lines, but just to clarify exactly what needs to be cast when, and therefore where parentheses need to go. Unlike other types in PHP, SimpleXML objects are never automatically cast to float
, so mathematical operators like *
cast them to int
instead. (I filed this is as a bug, but it was closed on the grounds that PHP's internals don't have a way of implementing it.)
You therefore need to cast the SimpleXML value to a float
(AKA double
) before applying any mathematical operations to it. In order to force this in the right order without an intermediate assignment, you would need exactly one set of extra parentheses: ((float)$simplexml_value) * $some_number
.
However, as the Operator Precedence table in the PHP manual shows, type casts such as (float)
are already higher precedence than *
, which is higher precedence than .
, so the below code runs as desired without any extra parentheses (live demo in multiple PHP versions):
foreach ($xml->children() as $second_level) {
echo $second_level->attributes()->id . "<br>";
echo (float)$second_level->attributes()->width * 10 . "<br>";
echo (float)$second_level->attributes()->height * 10 . "<br>";
}
Assigning to an intermediate variable immediately after casting will also work, as the multiplication will prefer to convert the integer
10 to a float
than convert the float
variable to an integer
(live demo):
foreach ($xml->children() as $second_level) {
echo $second_level->attributes()->id . "<br>";
$width = (float)$second_level->attributes()->width;
echo $width * 10 . "<br>";
$height = (float)$second_level->attributes()->height;
echo $height * 10 . "<br>";
}
That is because 10
is an integer value, thus the result of that equation will be an integer value too. You have to cast all values to floats.
foreach ($xml->children() as $second_level) {
echo $second_level->attributes()->id."<br>";
echo (float) ((float) $second_level->attributes()->width * (float) 10)."<br>";
echo (float) ((float) $second_level->attributes()->height * (float) 10)."<br>";
}
EDIT: Ubuntu 13.04 XAMPP with php 5.4.16, this worked:
<?php
$xml = new SimpleXMLElement(
'<DOM>
<TAB id="ID1" width="30.1" height="0.5" ></TAB>
<TAB id="ID2" width="15.7" height="1.8" ></TAB>
</DOM>');
foreach ($xml->children() as $second_level) {
echo $second_level->attributes()->id."<br>";
echo (float) ((float) $second_level->attributes()->width * 10)."<br>";
echo (float) ((float) $second_level->attributes()->height * 10)."<br>";
}
Cast the values to double by this code:
(double) ($second_level->attributes()->width) * 10