有这么个需求, 将一些地址库json数据需要转成xml格式, 而且xml里的层次为 address->province->city->county
json截取自微擎-人人商城中的foxui.citydata.min.js, 需要转成xml格式
// 要转义的json字段
[
{
"text":"北京市",
"children":[
{
"text":"北京辖区",
"children":[
"东城区",
"西城区",
"崇文区",
"宣武区",
"朝阳区",
"丰台区",
"石景山区",
"海淀区",
"门头沟区",
"房山区",
"通州区",
"顺义区",
"昌平区",
"大兴区",
"怀柔区",
"平谷区"
]
},
{
"text":"北京辖县",
"children":[
"密云县",
"延庆县"
]
}
]
},
{
"text":"天津市",
"children":[
{
"text":"天津辖区",
"children":[
"和平区",
"河东区",
"河西区",
"南开区",
"河北区",
"红桥区",
"塘沽区",
"汉沽区",
"大港区",
"东丽区",
"西青区",
"津南区",
"北辰区",
"武清区",
"宝坻区"
]
},
{
"text":"天津辖县",
"children":[
"宁河县",
"静海县",
"蓟县"
]
}
]
}
]
最终转义成的xml格式
<?xml version="1.0" encoding="utf-8"?>
<address>
<province name="请选择省份">
<city name="请选择城市">
<county name="请选择区域"/>
</city>
</province>
<province name="北京市">
<city name="北京辖区">
<county name="东城区" />
<county name="西城区" />
<county name="崇文区" />
<county name="宣武区" />
<county name="朝阳区" />
<county name="丰台区" />
<county name="石景山区" />
<county name="海淀区" />
<county name="门头沟区" />
<county name="房山区" />
<county name="通州区" />
<county name="顺义区" />
<county name="昌平区" />
<county name="大兴区" />
<county name="怀柔区" />
<county name="平谷区" />
</city>
<city name="北京辖县">
<county name="密云县" />
<county name="延庆县" />
</city>
</province>
<province name="天津市">
<city name="天津辖区">
<county name="和平区" />
<county name="河东区" />
<county name="河西区" />
<county name="南开区" />
<county name="河北区" />
<county name="红桥区" />
<county name="塘沽区" />
<county name="汉沽区" />
<county name="大港区" />
<county name="东丽区" />
<county name="西青区" />
<county name="津南区" />
<county name="北辰区" />
<county name="武清区" />
<county name="宝坻区" />
</city>
<city name="天津辖县">
<county name="宁河县" />
<county name="静海县" />
<county name="蓟县" />
</city>
</province>
</address>
先来看看菜鸟文档给的json转xml 源码 PHP XML 与 JSON 相互转换
<?php
$json = stream_get_contents(STDIN);
$data = @json_decode($json, false);
if (!is_array($data) && !is_object($data)) {
echo 'ERROR: Invalid JSON given' . PHP_EOL;
exit(1);
}
class Exporter
{
private $root = 'document';
private $indentation = ' ';
// TODO: private $this->addtypes = false; // type="string|int|float|array|null|bool"
public function export($data)
{
$data = array($this->root => $data);
echo '<?xml version="1.0" encoding="UTF-8">';
$this->recurse($data, 0);
echo PHP_EOL;
}
private function recurse($data, $level)
{
$indent = str_repeat($this->indentation, $level);
foreach ($data as $key => $value) {
echo PHP_EOL . $indent . '<' . $key;
if ($value === null) {
echo ' />';
} else {
echo '>';
if (is_array($value)) {
if ($value) {
$temporary = $this->getArrayName($key);
foreach ($value as $entry) {
$this->recurse(array($temporary => $entry), $level + 1);
}
echo PHP_EOL . $indent;
}
} else if (is_object($value)) {
if ($value) {
$this->recurse($value, $level + 1);
echo PHP_EOL . $indent;
}
} else {
if (is_bool($value)) {
$value = $value ? 'true' : 'false';
}
echo $this->escape($value);
}
echo '</' . $key . '>';
}
}
}
private function escape($value)
{
// TODO:
return $value;
}
private function getArrayName($parentName)
{
// TODO: special namding for tag names within arrays
return $parentName;
}
}
$exporter = new Exporter();
$exporter->export($data);
依照写的一个样例:
class Exporter
{
// 原理基本上就是:把你的数据,拼一个数组,key是xml的标识,value是循环输出的内容.然后递归
private $root = 'address';
private $indentation = ' ';
public $ii = 0;
// TODO: private $this->addtypes = false; // type="string|int|float|array|null|bool"
// 输出拼接xml
public function export($data)
{
$data = array($this->root => $data);
echo '<?xml version="1.0" encoding="UTF-8">';
$this->recurse($data, 0);
echo PHP_EOL;
}
private function recurse($data, $level)
{
$indent = str_repeat($this->indentation, $level);
foreach ($data as $key => $value) {
// 分别在第几层头部需要输出?东西
if ($level == 0) {
$key = 'address';
echo PHP_EOL . $indent . '<' . 'address';
} else if ($level == 1) {
// 第一层时需要输出"请选择xx省"之类的东西
if ($this->ii == 0) {
echo PHP_EOL . $indent . '<province name="Please choose Negeri">';
echo PHP_EOL . $indent . $indent . '<city name="Please choose Bahagian">';
echo PHP_EOL . $indent . $indent . $indent . '<county name="Please choose Daerah"/>';
echo PHP_EOL . $indent . $indent . '</city>';
echo PHP_EOL . $indent . '</province>';
}
$key = 'province';
echo PHP_EOL . $indent . '<' . 'province name="' . $value['text'] . '"';
} else if ($level == 2) {
$key = 'city';
echo PHP_EOL . $indent . '<' . 'city name="' . $value['text'] . '"';
} else if ($level == 3) {
$key = 'county';
echo PHP_EOL . $indent . '<' . 'county name="' . $value . '"';
}
if ($value === null || $level == 3) {
echo ' />';
} else {
echo '>';
if (is_array($value) && !empty($value)) {
$temporary = $this->getArrayName($key);
if ($level == 0) {
foreach ($value as $entry) {
$this->recurse(array($temporary => $entry), $level + 1);
}
} else {
foreach ($value['children'] as $entry) {
$this->recurse(array($temporary => $entry), $level + 1);
}
}
echo PHP_EOL . $indent;
} else {
if (is_bool($value)) {
$value = $value ? 'true' : 'false';
}
echo $this->escape($value);
}
if ($level == 0) {
echo '</address>';
} else if ($level == 1) {
echo '</province>';
} else if ($level == 2) {
echo '</city>';
} else if ($level == 3) {
}
}
$this->ii++;
}
}
private function escape($value)
{
// TODO:
return $value;
}
private function getArrayName($parentName)
{
// TODO: special namding for tag names within arrays
return $parentName;
}
}
// 调用
$model = '[{"text":"北京市","children":[{"text":"北京辖区","children":["东城区","西城区","崇文区","宣武区","朝阳区","丰台区","石景山区","海淀区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","怀柔区","平谷区"]},{"text":"北京辖县","children":["密云县","延庆县"]}]},{"text":"天津市","children":[{"text":"天津辖区","children":["和平区","河东区","河西区","南开区","河北区","红桥区","塘沽区","汉沽区","大港区","东丽区","西青区","津南区","北辰区","武清区","宝坻区"]},{"text":"天津辖县","children":["宁河县","静海县","蓟县"]}]}]';
$arr = json_decode($model, true);
$exporter = new Exporter();
$exporter->export($arr);
当时急着用,写的有点直,没考虑到封装性与优化问题,能用就直接上了.