【问题标题】:PHP server-side covert xml to json, outcome has different formatPHP服务器端将xml转换为json,结果有不同的格式
【发布时间】:2018-07-30 14:20:19
【问题描述】:

我正在尝试将xml转换为json,我尝试使用以下代码,

$xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA);
$json = json_encode($xml);
$arr = json_decode($json,true);

这段代码运行良好,但有一个问题, XML文件中的某些内容有可能有多个值或只有一个值,这些值的XML转换结果会有所不同,对于单值它将是与单个值关联的键,对于多值,它将返回一个数组。我的问题是如何确保返回值是一致的。

这里是返回值的例子。

多值

"item": [
                    {
                        "product_id": "XL2",
                        "description": "222 For You",
                        "d_image": "D_NUL.png",
                        "m_image": "M_NUL.png",
                        "dm_image": "DM_NUL.png",
                        "whole_toppings": {
                            "topping": "PEPPERONI"
                        },
                        "left_toppings": {
                            "topping": "MUSHROOMS"
                        },
                        "right_toppings": {
                            "topping": "ANCHOVIES"
                        },
                        "crust": "THICK CRUST (REGULAR)",
                        "sauce": "REGULAR",
                        "cook": "REGULAR"
                    },
                    {
                        "product_id": "XLA",
                        "description": [],
                        "d_image": "D_NUL.png",
                        "m_image": "M_NUL.png",
                        "dm_image": "DM_NUL.png",
                        "whole_toppings": {
                            "topping": "PEPPERONI"
                        },
                        "left_toppings": {
                            "topping": "MUSHROOMS"
                        },
                        "right_toppings": {
                            "topping": "ANCHOVIES"
                        },
                        "crust": "THICK CRUST (REGULAR)",
                        "sauce": "REGULAR",
                        "cook": "REGULAR"
                    }
                ]
            },

单值:

"item": {
                    "product_id": "MMED",
                    "description": "Mediterranean",
                    "d_image": "D_NUL.png",
                    "m_image": "M_NUL.png",
                    "dm_image": "DM_NUL.png",
                    "whole_toppings": {
                        "topping": [
                            "PEPPERONI",
                            "NO ONIONS",
                            "NO FETA CHEESE",
                            "NO SEASONED BEEF",
                            "NO TOMATOES"
                        ]
                    },

我的预期结果是

"item": [{
                    "product_id": "MMED",
                    "description": "Mediterranean",
                    "d_image": "D_NUL.png",
                    "m_image": "M_NUL.png",
                    "dm_image": "DM_NUL.png",
                    "whole_toppings": {
                        "topping": [
                            "PEPPERONI",
                            "NO ONIONS",
                            "NO FETA CHEESE",
                            "NO SEASONED BEEF",
                            "NO TOMATOES"
                        ]
                    }],

感谢您的帮助。

【问题讨论】:

  • 所以你希望 "product_id": "XL2" 改为 "product_id": ["XL2"]
  • if item:{ } 只有一个值,而不是只返回一个对象,我希望返回值是一个包含一个对象的数组。谢谢!
  • 我不明白,您能否提供一个问题中预期输出的示例?
  • "item":[ { "product_id": "MMED", "description": "Mediterranean", "d_image": "D_NUL.png", "m_image": "M_NUL.png", “dm_image”:“DM_NUL.png”、“whole_toppings”:{“topping”:[“PEPPERONI”、“NO ONIONS”、“NO FETA CHEESE”、“NO SEASONED BEEF”、“NO TOMATOES”] }]、
  • 我根本看不懂。将该信息编辑到您的问题中。

标签: php json xml


【解决方案1】:

您依赖于 SimpleXML 的自动对象序列化。这里没有可用的信息表明 XML 元素可能具有同名的兄弟姐妹。该信息不存在,因此没有自动转换可以创建您想要的输出。 (并非没有提供该信息的东西。)

您将需要遍历 XML 树并生成您的特定输出。这是一个简化的示例:

$xml = <<<'XML'
<items>
  <item>
    <product_id>1</product_id>
    <whole_toppings>
      <topping>PEPPERONI</topping>
    </whole_toppings>
  </item>
  <item>
    <product_id>2</product_id>
    <whole_toppings>
      <topping>PEPPERONI</topping>
      <topping>MUSHROOMS</topping>
    </whole_toppings>
  </item>
</items>
XML;

$itemsElement = new SimpleXMLElement($xml);

$items = [];
foreach ($itemsElement->item as $itemElement) {
  $item = [
    'product_id' => (string)$itemElement->product_id,
    'whole_toppings' => [] ,
    'left_toppings' => [] 
  ];
  if ($itemElement->whole_toppings) {
    foreach ($itemElement->whole_toppings->topping as $toppingElement) {
     $item['whole_toppings'][] = (string)$toppingElement;
    }
  }
  if ($itemElement->left_toppings) {
    foreach ($itemElement->left_toppings->topping as $toppingElement) {
       $item['left_toppings'][] = (string)$toppingElement;
    }
  }
  $items[] = $item;
}

echo json_encode($items, JSON_PRETTY_PRINT);

输出:

[
  {
    "product_id":"1",
    "whole_toppings":[
      "PEPPERONI"
    ],
    "left_toppings":[

    ]
  },
  {
    "product_id":"2",
    "whole_toppings":[
      "PEPPERONI",
      "MUSHROOMS"
    ],
    "left_toppings":[

    ]
  }
]

最初需要做更多的工作,但它为您提供了对输出的更多控制。如您所见,JSON 输出包含两个产品的 whole_toppings 数组和 left_toppings 数组(但在 XML 中没有标记)。

要优化它,您可以将逻辑重构为辅助函数/方法。

function readToppingsList(
  SimpleXMLElement $itemElement, 
  string $listName, 
  string $itemName = 'topping'
): array {
  $toppings = [];
  if ($itemElement->{$listName}) {
    foreach ($itemElement->{$listName}->{$itemName} as $toppingElement) {
      $toppings[] = (string)$toppingElement;
    }
  }
  return $toppings;
}

$itemsElement = new SimpleXMLElement($xml);

$items = [];
foreach ($itemsElement->item as $itemElement) {
  $item = [
    'product_id' => (string)$itemElement->product_id,
    'whole_toppings' => readToppingsList($itemElement, 'whole_toppings'),
    'left_toppings' => readToppingsList($itemElement, 'left_toppings')
  ];
  $items[] = $item;
}

echo json_encode($items, JSON_PRETTY_PRINT);

【讨论】:

  • 非常感谢,这对您有很大帮助。我想知道我是否可以为这种情况提供最终的自动化解决方案,因为后端提供程序没有为我提供包含数据源,这意味着任何具有兄弟的属性都会导致同样的问题,但似乎没有自动化它的方法,我只会为每一个手动转换。感谢您的帮助
  • 问题在于格式之间的差异——而不是格式本身。对于像&lt;list&gt;&lt;title/&gt;&lt;item/&gt;&lt;item/&gt;&lt;/list&gt; 这样的XML 将是有效且一致的。想想(X)HTML。它只是不转换为 JSON,因为它在对象和数组之间产生了明显的区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
相关资源
最近更新 更多