1

I need help with this issue, it seems I can't get targetCurrency out of the SimpleXMLElement Object

$xmlString = <<<XML
<channel>
    <title>XML ~~ Exchange Rates ~~</title>
    <language>en</language>
    <item>
        <baseCurrency>USD</baseCurrency>
        <targetCurrency>EUR</targetCurrency>
        <targetName>Euro</targetName>
        <exchangeRate>0.90900497</exchangeRate>
    </item>
</channel>
XML;

$xml = simplexml_load_string($xmlString);
        
foreach($xml->item as $rate){
    
    $rate       = (string) $rate->exchangeRate;
    $curr_code  = (string) $rate->targetCurrency;
     
    $money[] = array('rate' => $rate, 'curr_code' =>  $curr_code);
}
        
print_r($money);

This outputs:

Array
(
    [0] => Array
        (
            [rate] => 0.90947603
            [curr_code] => 
        )
)

[curr_code] should output 'EUR'.

How can I fix it?

2 Answers 2

1

You are using the same variable name for two different things:

foreach($xml->item as $rate){
    // at this point, $rate is the <item> element

    $rate       = (string) $rate->exchangeRate;
    // now $rate is a string with the exchange rate

    $curr_code  = (string) $rate->targetCurrency;
    // so now this won't work

    $money[] = array('rate' => $rate, 'curr_code' =>  $curr_code);
}

If you were running with display_errors switched on or checking your logs, you would have seen a message like this:

Notice: Trying to get property 'targetCurrency' of non-object

Or in PHP 8, this:

Warning: Attempt to read property "targetCurrency" on string


The fix is simply to name your variables more carefully:

foreach($xml->item as $itemElement){
    $rate = (string) $itemElement->exchangeRate;
    $curr_code  = (string) $itemElement->targetCurrency;
    $money[] = array('rate' => $rate, 'curr_code' =>  $curr_code);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Whoops, you are right, I overlooked that. Thank you!
0

Try it using xpath instead:

$items  = $xml->xpath("//item");
foreach($items as $item){
    $rate = $item->xpath('.//exchangeRate')[0];
    $curr_code  = $item->xpath('.//targetCurrency')[0]; 
    $money[] = array('rate' => $rate, 'curr_code' =>  $curr_code);
 }
    
print_r($money);

The output should be as exptected.

3 Comments

So peel out one more layer. Works perfectly, thank you.
@yello Glad it worked for yu!
The reason this works actually has nothing to do with XPath, which is massive overkill for this task; you fixed the actual bug without noticing, by changing foreach($items as $rate) to foreach($items as $item)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.