XML duplicate values - PHP

Solution 1:

You can regroup in an array (using the same key), before to write the XML :


$iso_curr_xml = simplexml_load_file('https://wpcoder.co.uk//links/sir_prakash_webdev1/ws7/curr_old.xml');
$rates_json_url = file_get_contents('https://freecurrencyapi.net/api/v2/latest?apikey=4392e6c0-67d6-11ec-82cc-4d7a41b7625b&base_currency=GBP');

$rate_json_obj = json_decode($rates_json_url);
$ts = $rate_json_obj->query->timestamp;


// Regroup by crcode :

$codes = [];
foreach ($iso_curr_xml->CcyTbl->CcyNtry as $xml_res) {
    $crcode = (string)$xml_res->Ccy;

    // if the key doesn't exists, get shared data 
    if (!isset($codes[$crcode])) {
        $codes[$crcode]['ccode'] = (string)$xml_res->Ccy;
        $codes[$crcode]['cname'] = (string)$xml_res->CcyNm;
        $codes[$crcode]['crate'] = $rate_json_obj->data->{$crcode} ?? 0;
    }

    // in all cases, add country name
    $codes[$crcode]['cntry'][] = (string)$xml_res->CtryNm;
}

// Now, generate the XML (based on the previous array) :

$currencies = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><currencies ts="' . $ts . '" />');
foreach ($codes as $crcode => $data) {
    $currency = $currencies->addChild('currency');
    $currency->addAttribute('code', $crcode);
    $currency->addChild('ccode', $data['ccode']);
    $currency->addChild('cname', $data['cname']);
    $currency->addChild('cntry', implode(', ', $data['cntry'])); // implode countries
    $currency->addChild('cname', $data['crate']);
}
$currencies->asXML('currency.xml');

Output:

<?xml version="1.0" encoding="UTF-8"?>
<currencies ts="1642451660">
   <currency code="AFN">
      <ccode>AFN</ccode>
      <cname>Afghani</cname>
      <cntry>AFGHANISTAN</cntry>
      <cname>143.232437</cname>
   </currency>
   <currency code="EUR">
      <ccode>EUR</ccode>
      <cname>Euro</cname>
      <cntry>ÅLAND ISLANDS, ANDORRA, AUSTRIA, BELGIUM, CYPRUS, ESTONIA, EUROPEAN UNION, FINLAND, FRANCE, FRENCH GUIANA, FRENCH SOUTHERN TERRITORIES (THE), GERMANY, GREECE, GUADELOUPE, HOLY SEE (THE), IRELAND, ITALY, LATVIA, LITHUANIA, LUXEMBOURG, MALTA, MARTINIQUE, MAYOTTE, MONACO, MONTENEGRO, NETHERLANDS (THE), PORTUGAL, RÉUNION, SAINT BARTHÉLEMY, SAINT MARTIN (FRENCH PART), SAINT PIERRE AND MIQUELON, SAN MARINO, SLOVAKIA, SLOVENIA, SPAIN</cntry>
      <cname>1.198999</cname>
   </currency>
   <!-- ... -->
</currencies>