如何为基于文档的数据库正确准备 XML 个文件?
How can I properly prepare XML files for document-based database?
在 PHP 中将 XML 转换为 JSON 时如何将 @attributes 移动到该元素的根?
我发现将 XML 文件转换为 json_encode
的最简单方法。但我想去掉 @attributes,因此 id
和 name
将直接位于根目录,因为我会将所有内容直接导入数据库进行操作和计算。 (数据来自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
$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"
}
},
与其将其视为 "convert an arbitrary XML file to JSON",不如将其视为 "extract the information I want from an XML file" 加上 "serialise that information as JSON"。
如果文件始终具有您显示的结构,您可以轻松提取顶层的 id
和 name
:
$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)。
在 PHP 中将 XML 转换为 JSON 时如何将 @attributes 移动到该元素的根?
我发现将 XML 文件转换为 json_encode
的最简单方法。但我想去掉 @attributes,因此 id
和 name
将直接位于根目录,因为我会将所有内容直接导入数据库进行操作和计算。 (数据来自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
$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"
}
},
与其将其视为 "convert an arbitrary XML file to JSON",不如将其视为 "extract the information I want from an XML file" 加上 "serialise that information as JSON"。
如果文件始终具有您显示的结构,您可以轻松提取顶层的 id
和 name
:
$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)。