PHP SimpleXML 中的 XML 到 JSON 转换

Posted

技术标签:

【中文标题】PHP SimpleXML 中的 XML 到 JSON 转换【英文标题】:XML to JSON conversion in PHP SimpleXML 【发布时间】:2015-02-22 09:57:12 【问题描述】:
            $data = "<QRYRESULT>
            <ISSUCCESS>Y</ISSUCCESS>
            <EBLCUSTOMER ACCOUNTNO='11111'>
            <CUSTACCTNO>121212</CUSTACCTNO>
            <ACCTSTATUS>active</ACCTSTATUS>
            <CCYDESC>BDT</CCYDESC>
            <BALANCE>9999</BALANCE>
            <AVAILABLEBALANCE>99</AVAILABLEBALANCE>
            <CUSTOMERNAME>cus_name</CUSTOMERNAME>
            <AMOUNTONHOLD>1000</AMOUNTONHOLD>
            <ODLIMIT>99</ODLIMIT>
            </EBLCUSTOMER>
            </QRYRESULT>";

这是我要转换的 XML 字符串。我使用了以下代码。

           $result = str_replace(array("\n", "\r", "\t"), '', $data);
           $xml = simplexml_load_string($result);
           $object = new stdclass();
           $object->webservice[] = $xml;
           $result = json_encode($object);
           header('content-Type: application/json');
           echo $result;

我得到以下 json 数据。

  
     "webservice": [
       
        "ISSUCCESS": "Y",
        "CUSTSUMMARY": 
            "@attributes": 
                "ACCOUNT": "11111"
            ,
            "IDACCOUNT": "1010101",
            "CODACCTCURR": "BDT",
            "NUMBALANCE": "99999",
            "ACCTDESC": "22222",
            "PRDNAME": "name"
            
         
      ]
   

但我不想要“@attributes”。我想要如下输出:


  "QRYRESULT": 
   "ISSUCCESS": "Y",
   "EBLCUSTOMER": 
    "-ACCOUNTNO": "11111",
    "CUSTACCTNO": "121212",
    "ACCTSTATUS": "active",
    "CCYDESC": "BDT",
    "BALANCE": "9999",
     "AVAILABLEBALANCE": "99",
     "CUSTOMERNAME": "cus_name",
     "AMOUNTONHOLD": "1000",
    "ODLIMIT": "99"
    
   
  

我该怎么做?

【问题讨论】:

【参考方案1】:

您不希望在 JSON 中编码“@attributes”字段,但这是 php JSON 序列化 SimpleXMLElement 的标准方式。

正如您所说的,您需要更改 PHP JSON 序列化对象的方式。这可以通过您自己使用 SimpleXMLElement 实现 JsonSerializable 然后根据需要提供 JSON 序列化来实现:

class JsonSerializer extends SimpleXmlElement implements JsonSerializable

    /**
     * SimpleXMLElement JSON serialization
     *
     * @return null|string
     *
     * @link http://php.net/JsonSerializable.jsonSerialize
     * @see JsonSerializable::jsonSerialize
     */
    function jsonSerialize()
    
        // jishan's SimpleXMLElement JSON serialization ...

        return $serialized;
    

例如通过将属性用作所有子元素的字段。

然后您可以轻松地集成它,例如而不是

$xml = simplexml_load_string($result);

你可以使用

$xml = simplexml_load_string($result, 'JsonSerializer');

或者只是

$xml = new JsonSerializer($result);

你的函数的其余部分工作相同,但只是你的愿望序列化。

例子:

$result = str_replace(array("\n", "\r", "\t"), '', $data);
$xml = new JsonSerializer($result);
$object = new stdclass();
$object->webservice[] = $xml;
$result = json_encode($object, JSON_PRETTY_PRINT);
header('content-Type: application/json');
echo $result;

输出:


    "webservice": [
        
            "EBLCUSTOMER": 
                "ACCOUNTNO": "11111",
                "CUSTACCTNO": "121212",
                "ACCTSTATUS": "active",
                "CCYDESC": "BDT",
                "BALANCE": "9999",
                "AVAILABLEBALANCE": "99",
                "CUSTOMERNAME": "cus_name",
                "AMOUNTONHOLD": "1000",
                "ODLIMIT": "99"
            
        
    ]

上例的序列化函数为:

function jsonSerialize()

    // text node (or mixed node represented as text or self closing tag)
    if (!count($this)) 
        return $this[0] == $this
            ? trim($this) : null ;
    

    // process all child elements and their attributes
    foreach ($this as $tag => $element) 
        // attributes first
        foreach ($element->attributes() as $name => $value) 
            $array[$tag][$name] = $value;
        
        // child elements second
        foreach($element as $name => $value) 
            $array[$tag][$name] = $value;
        
    

    return $array;

这里有一些注意事项:

在序列化过程中,您必须注意自己的元素类型。对于没有子元素的单个元素,区分是在顶部完成的。如果您需要对这些进行属性处理,则需要添加它。 trim($this) 可能已经避免了您尝试使用$result = str_replace(array("\n", "\r", "\t"), '', $data); 捕获的问题。 SimpleXMLElement 在任何情况下都会 JSON 序列化“\r”字符(SimpleXMLElement 使用“\n”作为中断)。另外你可能对whitespace normalization in XML的规则感兴趣。 如果属性与子元素具有相同的名称,它将被子元素覆盖。 如果一个子元素跟在另一个同名子元素之后,它将被覆盖。

最后两点只是为了让示例代码保持简单。我的一系列博客文章中给出了一种与 SimpleXMLElement 的标准 PHP JSON 序列化一致的方法。

此过程的基础知识和示例 JsonSerialize 实现可在第三篇文章中找到:SimpleXML and JSON Encode in PHP – Part III and End。

另一个相关的问题是:

PHP convert XML to JSON group when there is one child

【讨论】:

当我使用 codeigniter 框架时,我所做的是在我的控制器类中编写了 jsonSerialize() 函数,并从我正在处理 XML 到 json 转换的函数中调用它,例如 $xml = $ this->jsonSerialize();然后我的代码的其余部分,但我收到以下错误:`致命错误:调用未定义的方法 CI_Benchmark::attributes() @hakre 先尝试让它在没有 Codeigniter 的情况下运行,以便您检查它是否工作。类名 CI_Benchmark 可能表明此时某些东西与 Codeigniter 混合在一起并具有误导性。【参考方案2】:
$fileContents= file_get_contents("https://www.feedforall.com/sample.xml");
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
$array = json_decode($json,TRUE); // convert the JSON-encoded string to a PHP variable
return $array;

最好的例子:

【讨论】:

以上是关于PHP SimpleXML 中的 XML 到 JSON 转换的主要内容,如果未能解决你的问题,请参考以下文章

雷林鹏分享:PHP SimpleXML

PHP SimpleXML 不保留 XML 属性中的换行符

使用 SimpleXML/DOM 通过 php 将节点从一个 XML 复制到另一个

PHP 5 SimpleXML 函数

使用来自子元素的数据在 php 中使用 simplexml 选择其他元素中的数据

当我尝试做 simplexml_load_file 时出现 XML 错误