Home > OS >  Converting XML to json using php
Converting XML to json using php

Time:01-03

I am not much familiar with XML. can you guys please help me with convering this xml to json using php?. this is an API response.

<?xml version="1.0" encoding="utf-8"?>
<ecomexpress-objects version="1.0">
    <object pk="1" model="awb">
<field type="BigIntegerField" name="awb_number">115979601</field>
<field type="CharField" name="orderid">001</field>
<field type="FloatField" name="actual_weight">0.8</field>
<field type="CharField" name="origin">DELHI-DLW</field>
<field type="CharField" name="destination">DELHI-DLW</field>
<field type="CharField" name="current_location_name">DELHI-DLW</field>
<field type="CharField" name="current_location_code">DLW</field>
<field type="CharField" name="customer">Freshbells - 471459</field>
<field type="CharField" name="consignee">Forward</field>
<field type="CharField" name="pickupdate"></field>
<field type="CharField" name="status">Shipment Uploaded</field>
<field type="CharField" name="tracking_status">Shipment Not Handed over</field>
<field type="CharField" name="reason_code"></field>
<field type="CharField" name="reason_code_description"></field>
<field type="CharField" name="reason_code_number">001</field>
<field type="CharField" name="receiver"></field>
<field type="CharField" name="lat">0.0000000</field>
<field type="CharField" name="long">0.0000000</field>
<field type="CharField" name="rev_pickup_signature" ></field>
<field type="CharField" name="rev_pickup_packed_image" ></field>
<field type="CharField" name="rev_pickup_open_image" ></field>

</ecomexpress-objects>

I have tried with so many solution found here. but that doesn't work.

CodePudding user response:

This XML seems to serialize data model objects. It is fairly easy to read them into stdClass objects.

// bootstrap DOM Xpath
$document = new DOMDocument();
$document->loadXML(getXMLString());
$xpath = new DOMXpath($document);

$objects = [];
// iterate object elements
foreach ($xpath->evaluate('/ecomexpress-objects/object') as $objectNode) {
    $object = new stdClass();
    // iterate field elements
    foreach ($xpath->evaluate('field', $objectNode) as $fieldNode) {
        // read attributes
        $name = $fieldNode->getAttribute('name');
        $type = $fieldNode->getAttribute('type');
        // read field content and cast according to type
        switch ($type) {
            case 'BigIntegerField':
                $object->{$name} = (int)$fieldNode->textContent;
                break;
            case 'FloatField':
                $object->{$name} = (float)$fieldNode->textContent;
                break;
            default:
                $object->{$name} = $fieldNode->textContent;
        }
    }
    $objects[] = $object;
}
echo json_encode($objects, JSON_PRETTY_PRINT);

function getXMLString(): string {
    return <<<'XML'
<?xml version="1.0" encoding="utf-8"?>
<ecomexpress-objects version="1.0">
    <object pk="1" model="awb">
<field type="BigIntegerField" name="awb_number">115979601</field>
<field type="CharField" name="orderid">001</field>
<field type="FloatField" name="actual_weight">0.8</field>
<field type="CharField" name="origin">DELHI-DLW</field>
<field type="CharField" name="destination">DELHI-DLW</field>
<field type="CharField" name="current_location_name">DELHI-DLW</field>
<field type="CharField" name="current_location_code">DLW</field>
<field type="CharField" name="customer">Freshbells - 471459</field>
<field type="CharField" name="consignee">Forward</field>
<field type="CharField" name="pickupdate"></field>
<field type="CharField" name="status">Shipment Uploaded</field>
<field type="CharField" name="tracking_status">Shipment Not Handed over</field>
<field type="CharField" name="reason_code"></field>
<field type="CharField" name="reason_code_description"></field>
<field type="CharField" name="reason_code_number">001</field>
<field type="CharField" name="receiver"></field>
<field type="CharField" name="lat">0.0000000</field>
<field type="CharField" name="long">0.0000000</field>
<field type="CharField" name="rev_pickup_signature" ></field>
<field type="CharField" name="rev_pickup_packed_image" ></field>
<field type="CharField" name="rev_pickup_open_image" ></field>
    </object>
</ecomexpress-objects>
XML;
}

Output:

[
    {
        "awb_number": 115979601,
        "orderid": "001",
        "actual_weight": 0.8,
        "origin": "DELHI-DLW",
        "destination": "DELHI-DLW",
        "current_location_name": "DELHI-DLW",
        "current_location_code": "DLW",
        "customer": "Freshbells - 471459",
        "consignee": "Forward",
        "pickupdate": "",
        "status": "Shipment Uploaded",
        "tracking_status": "Shipment Not Handed over",
        "reason_code": "",
        "reason_code_description": "",
        "reason_code_number": "001",
        "receiver": "",
        "lat": "0.0000000",
        "long": "0.0000000",
        "rev_pickup_signature": "",
        "rev_pickup_packed_image": "",
        "rev_pickup_open_image": ""
    }
]

This approach could be extended with actual model classes in your code. Here is a very basic approach for this (without error handling):


// define a class for the model
class AWB implements JsonSerializable {
    
    public readonly int $awb_number;
    public readonly string $orderid;
    public readonly float $actual_weight;
    
    public function __construct(stdClass $values) {
        foreach ((array)$values as $name => $value) {
            if (property_exists($this, $name)) {
                $this->{$name} = $value;
            }
        }
    }
    
    public function jsonSerialize(): mixed {
        return get_object_vars($this);
    }
}

// mapping array
$models = [
  'awb' => AWB::class    
];

$document = new DOMDocument();
$document->loadXML(getXMLString());
$xpath = new DOMXpath($document);

$objects = [];
foreach ($xpath->evaluate('/ecomexpress-objects/object') as $objectNode) {
    $object = new stdClass();
    foreach ($xpath->evaluate('field', $objectNode) as $fieldNode) {
        // read field values - just like the previous example
    }
    // map model name to class
    $class = $models[$objectNode->getAttribute('model')];
    $objects[] = new $class($object);
}
echo json_encode($objects, JSON_PRETTY_PRINT);

Output:

[
    {
        "awb_number": 115979601,
        "orderid": "001",
        "actual_weight": 0.8
    }
]

Also PHP attributes could be used to map field names to properties.

  • Related