PHP read decimal integers from xml attributes

2020-04-11 06:33发布

问题:

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

回答1:

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


回答2:

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


回答3:

Cast the values to double by this code:

(double) ($second_level->attributes()->width) * 10


标签: php simplexml