【问题标题】:XML to JSON conversion in PHP SimpleXMLPHP SimpleXML 中的 XML 到 JSON 转换
【发布时间】: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"
    }
   }
  }

我该怎么做?

【问题讨论】:

    标签: php xml json


    【解决方案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

    另一个相关的问题是:

    【讨论】:

    • 当我使用 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;
    

    最好的例子:

    【讨论】:

      猜你喜欢
      • 2013-10-11
      • 1970-01-01
      • 2014-01-17
      • 1970-01-01
      • 2012-08-16
      • 2012-02-08
      • 2021-01-30
      • 1970-01-01
      • 2013-03-26
      相关资源
      最近更新 更多