phpjsonxmlsimplexmldocument-based

How can I properly prepare XML files for document-based database?


How can I move @attributes to the root of that element when converting XML to JSON in PHP?

The simplest way I found to convert my XML file is to json_encode. But I would like to get rid of the @attributes so id and name for example would be directly at the root as I'll be importing everything directly into a database for manipulation and computation. (Data are from 7 days to die for the curious).

How can I easily convert those XML files to json for I can then import those into my database without having those ugly @attributes? I understand their purpose but I have no need for them here, as you can see.

Small sample:

<block id="1" name="stone">
    <property name="Material" value="stone"/>
    <property name="Shape" value="Terrain"/>
    <property name="Mesh" value="terrain"/>
    <property name="Texture" value="1"/>
    <property name="ImposterExchange" value="imposterBlock" param1="97"/>
    <property name="DropScale" value="2"/>
    <property name="LPHardnessScale" value="2"/>
    <property name="Weight" value="125"/>
    <property name="Map.Color" value="100,100,100"/>
    <property class="RepairItems"> <property name="cobblestones" value="6"/> </property>
    <property name="HarvestOverdamage" value="true"/> <!-- default=true -->
    <drop event="Harvest" name="rockSmall" count="25" tool_category="harvestingTools"/>
    <drop event="Harvest" name="ironFragment" count="2" tool_category="harvestingTools"/>
    <drop event="Destroy" count="0"/>
    <drop event="Fall" name="rockSmall" count="50" prob="0.23" stick_chance="0"/>
    <drop event="Fall" name="ironFragment" count="4" prob="0.23" stick_chance="0"/>
    <drop event="Fall" name="destroyedStone" count="1" prob="0.1" stick_chance="0.5"/>
    <property name="CanMobsSpawnOn" value="true"/>
    <property name="EconomicValue" value="5"/>
    <property name="EconomicBundleSize" value="1"/>
    <property name="SellableToTrader" value="false"/>
</block>

Very small should-look-like:

{
    id: 1,
    name: "stone",
    property: [
        {
            name: "Material",
            value: "stone"
        },
        {
            name: "Shape",
            value: "Terrain"
        }
    ],
    drop: [
        {
            event: "Harverst",
            name: "rockSmall",
            count: 25
        },
        {
            event: "Harvest",
            name: "ironFragment",
            count: 2
        }
    ]
}

Solution

  • Let's try this:

    <?php
    
    $xmlContent = '<block id="1" name="stone">
        <property name="Material" value="stone"/>
        <property name="Shape" value="Terrain"/>
        <property name="Mesh" value="terrain"/>
        <property name="Texture" value="1"/>
        <property name="ImposterExchange" value="imposterBlock" param1="97"/>
        <property name="DropScale" value="2"/>
        <property name="LPHardnessScale" value="2"/>
        <property name="Weight" value="125"/>
        <property name="Map.Color" value="100,100,100"/>
        <property class="RepairItems"> <property name="cobblestones" value="6"/> </property>
        <property name="HarvestOverdamage" value="true"/> <!-- default=true -->
        <drop event="Harvest" name="rockSmall" count="25" tool_category="harvestingTools"/>
        <drop event="Harvest" name="ironFragment" count="2" tool_category="harvestingTools"/>
        <drop event="Destroy" count="0"/>
        <drop event="Fall" name="rockSmall" count="50" prob="0.23" stick_chance="0"/>
        <drop event="Fall" name="ironFragment" count="4" prob="0.23" stick_chance="0"/>
        <drop event="Fall" name="destroyedStone" count="1" prob="0.1" stick_chance="0.5"/>
        <property name="CanMobsSpawnOn" value="true"/>
        <property name="EconomicValue" value="5"/>
        <property name="EconomicBundleSize" value="1"/>
        <property name="SellableToTrader" value="false"/>
    </block>';
    
    $xml = simplexml_load_string($xmlContent, "SimpleXMLElement", LIBXML_NOCDATA);
    $array = object_to_array($xml);
    echo json_encode($array, JSON_PRETTY_PRINT);
    
    function object_to_array($input)
    {
        $return = array();
        foreach ((array)$input as $key => $value) {
            if (strpos($key, '@') === 0) {
                $key = substr($key, 1);
            }
            if (is_array($value) || is_object($value)) {
                $value = object_to_array($value);
            }
    
            $return[$key] = $value;
        }
        return $return;
    }
    

    Output:

    {
        "attributes": {
            "id": "1",
            "name": "stone"
        },
        "property": [
            {
                "attributes": {
                    "name": "Material",
                    "value": "stone"
                }
            },