【问题标题】:How can I properly prepare XML files for document-based database?如何为基于文档的数据库正确准备 XML 文件?
【发布时间】:2017-10-30 19:34:34
【问题描述】:

在 PHP 中将 XML 转换为 JSON 时,如何将 @attributes 移动到该元素的根?

我发现将我的 XML 文件转换为 json_encode 的最简单方法。但我想摆脱@attributes,例如idname 将直接位于根目录,因为我会将所有内容直接导入数据库进行操作和计算。 (数据是从 7 天到死的好奇)。

我怎样才能轻松地将这些 XML 文件转换为 json,然后我可以将它们导入到我的数据库中而没有那些丑陋的@attributes?我理解他们的目的,但我在这里不需要他们,如你所见。

小样本:

<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>

非常小的应该看起来像:

{
    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
        }
    ]
}

【问题讨论】:

标签: php json xml simplexml document-based


【解决方案1】:

让我们试试这个:

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

输出:

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

【讨论】:

    【解决方案2】:

    与其将其视为“将任意 XML 文件转换为 JSON”,不如将其视为“从 XML 文件中提取我想要的信息”加上“将该信息序列化为 JSON”。

    如果文件始终具有您显示的结构,您可以轻松提取顶层的idname

    $block = simplexml_load_string($my_xml_data);
    $extracted = [
        'id' => (int)$block['id'],
        'name' => (string)$block['name'],
    ];
    

    然后您可以循环遍历 property 元素,显式获取它们的名称和值:

    $extracted['property'] = [];
    foreach ( $block->property as $property ) {
        $extracted['property'][] = [
             'name' => (string)$property['name'],
             'value' => (string)$property['value']
        ];
    }
    

    如果你想让它更通用一点,你可以遍历所有属性并捕获它们的名称和值:

    $extracted['property'] = [];
    foreach ( $block->property as $property ) {
        $next_property = [];
        foreach ( $property->attributes() as $attr_name => $attr_value ) {
             $next_property[ $attr_name ] = (string)$attr_value;
        }
        $extracted['property'][] = $next_property;
    }
    

    然后,您可以使用相同的东西来获取 drop 节点,或者您可以使其非常通用并在您获得的任何顶级元素中啜饮:

    foreach ( $block->children() as $element_name => $element ) {
        // Note that unlike looping over an array, you will 
        //  get the same $element_name more than once!
        if ( ! isset($extracted[$element_name]) ) {
            $extracted[$element_name] = [];
        }
    
        $next_item = [];
        foreach ( $element->attributes() as $attr_name => $attr_value ) {
             $next_item[ $attr_name ] = (string)$attr_value;
        }
        $extracted[$element_name][] = $next_item;
    }
    

    请注意,这不是递归的,因为创建一个既涵盖所有可能的 XML 输入并产生良好结果的递归函数非常棘手。通过假设您正在处理的 XML 的一般形状不会改变,您可以决定要创建的数据结构(以及 JSON)的形状。

    【讨论】:

      猜你喜欢
      • 2017-01-03
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 2012-10-12
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 2010-12-08
      相关资源
      最近更新 更多