【问题标题】:PHP convert XML to JSONPHP 将 XML 转换为 JSON
【发布时间】:2012-02-08 11:27:43
【问题描述】:

我正在尝试将 xml 转换为 php 中的 json。如果我使用简单的 xml 和 json_encode 进行简单的转换,则 xml 中的任何属性都不会显示。

$xml = simplexml_load_file("states.xml");
echo json_encode($xml);

所以我试图像这样手动解析它。

foreach($xml->children() as $state)
{
    $states[]= array('state' => $state->name); 
}       
echo json_encode($states);

状态的输出是{"state":{"0":"Alabama"}} 而不是{"state":"Alabama"}

我做错了什么?

XML:

<?xml version="1.0" ?>
<states>
    <state id="AL">     
    <name>Alabama</name>
    </state>
    <state id="AK">
        <name>Alaska</name>
    </state>
</states>

输出:

[{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"}

变量转储:

object(SimpleXMLElement)#1 (1) {
["state"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AL"
  }
  ["name"]=>
  string(7) "Alabama"
}
[1]=>
object(SimpleXMLElement)#2 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AK"
  }
  ["name"]=>
  string(6) "Alaska"
}
}
}

【问题讨论】:

  • 请包含 XML 的 sn-p 和解析后的最终数组结构。 (var_dump 工作正常。)
  • 添加了输入、输出和var_dump
  • 有些应用需要"perfec XML-to-JSON map",即jsonML,见solution here

标签: php xml json


【解决方案1】:

看起来$state-&gt;name 变量正在保存一个数组。你可以使用

var_dump($state)

foreach 内进行测试。

如果是这种情况,您可以将foreach 内的行更改为

$states[]= array('state' => array_shift($state->name)); 

纠正它。

【讨论】:

  • 看起来属性是数组,但不是 $state->name
【解决方案2】:

我想通了。 json_encode 处理对象的方式不同于字符串。我将对象转换为字符串,它现在可以工作了。

foreach($xml->children() as $state)
{
    $states[]= array('state' => (string)$state->name); 
}       
echo json_encode($states);

【讨论】:

    【解决方案3】:

    很抱歉回答了一个旧帖子,但本文概述了一种相对简短、简洁且易于维护的方法。我自己测试过,效果很好。

    http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/

    <?php   
    class XmlToJson {
        public function Parse ($url) {
            $fileContents= file_get_contents($url);
            $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
            $fileContents = trim(str_replace('"', "'", $fileContents));
            $simpleXml = simplexml_load_string($fileContents);
            $json = json_encode($simpleXml);
    
            return $json;
        }
    }
    ?>
    

    【讨论】:

    • 如果您的 XML 中有同一个标签的多个实例,这将不起作用,json_encode 最终只会序列化标签的最后一个实例。
    • 致所有看到这个旧答案的人:请记住这是写的时间,也许考虑更现代的方法。
    【解决方案4】:

    为此,我使用了 Miles Johnson 的 TypeConverter。它可以使用Composer 安装。

    你可以用它写出这样的东西:

    <?php
    require 'vendor/autoload.php';
    use mjohnson\utility\TypeConverter;
    
    $xml = file_get_contents("file.xml");
    $arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
    echo json_encode($arr);
    

    【讨论】:

      【解决方案5】:

      如果您只想将 XML 的特定部分转换为 JSON,则可以使用 XPath 检索此部分并将其转换为 JSON。

      <?php
      $file = @file_get_contents($xml_File, FILE_TEXT);
      $xml = new SimpleXMLElement($file);
      $xml_Excerpt = @$xml->xpath('/states/state[@id="AL"]')[0]; // [0] gets the node
      echo json_encode($xml_Excerpt);
      ?>
      

      请注意,如果您的 Xpath 不正确,这将因错误而死。因此,如果您通过 AJAX 调用进行调试,我建议您也记录响应正文。

      【讨论】:

        【解决方案6】:

        3 行来自 XML 的 Json 和数组:

        $xml = simplexml_load_string($xml_string);
        $json = json_encode($xml);
        $array = json_decode($json,TRUE);
        

        【讨论】:

        • 此解决方案并非完美无缺。它完全丢弃了 XML 属性。所以&lt;person my-attribute='name'&gt;John&lt;/person&gt; 被解释为&lt;person&gt;John&lt;/person&gt;
        • $xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA);展平 cdata 元素。
        • @JakeWilson 可能已经过去了 2 年,并且修复了各种版本,但是在 PHP 5.6.30 上,此方法会生成所有数据。属性存储在@attributes 键下的数组中,因此它绝对完美无缺,而且非常漂亮。 3 行短代码完美解决了我的问题。
        • 如果你有多个命名空间,这不起作用,你可以只选择一个,它将传递到 $json_string :'(
        • 请记住,使用此解决方案时,当可能有多个同名节点时,一个节点将导致键仅指向一个元素,但多个节点将导致键指向 元素数组&lt;list&gt;&lt;item&gt;&lt;a&gt;123&lt;/a&gt;&lt;a&gt;456&lt;/a&gt;&lt;/item&gt;&lt;item&gt;&lt;a&gt;123&lt;/a&gt;&lt;/item&gt;&lt;/list&gt; -> {"item":[{"a":["123","456"]},{"a":"123"}]}。 php.net by ratfactor 的解决方案通过始终将元素存储在数组中来解决该问题。
        【解决方案7】:

        一个常见的陷阱是忘记json_encode() 不尊重具有textvalue 属性的元素。它将选择其中之一,即数据丢失。 下面的函数解决了这个问题。如果决定采用json_encode/decode 方式,建议使用以下函数。

        function json_prepare_xml($domNode) {
          foreach($domNode->childNodes as $node) {
            if($node->hasChildNodes()) {
              json_prepare_xml($node);
            } else {
              if($domNode->hasAttributes() && strlen($domNode->nodeValue)){
                 $domNode->setAttribute("nodeValue", $node->textContent);
                 $node->nodeValue = "";
              }
            }
          }
        }
        
        $dom = new DOMDocument();
        $dom->loadXML( file_get_contents($xmlfile) );
        json_prepare_xml($dom);
        $sxml = simplexml_load_string( $dom->saveXML() );
        $json = json_decode( json_encode( $sxml ) );
        

        这样做,&lt;foo bar="3"&gt;Lorem&lt;/foo&gt; 将不会在您的 JSON 中以 {"foo":"Lorem"} 结束。

        【讨论】:

        • 如果语法错误得到纠正,则不会编译并且不会产生所描述的输出。
        • 什么是$dom?这是从哪里来的?
        • $dom = new DOMDocument();是从哪里来的
        • 最后一行代码:$json = json_decode(json_encode($sxml)));应该是:$json = json_decode(json_encode($sxml));
        【解决方案8】:

        我想我参加聚会有点晚了,但我写了一个小函数来完成这项任务。它还负责属性、文本内容,即使具有相同节点名的多个节点是兄弟节点。

        免责声明: 我不是 PHP 本地人,所以请多多包涵。

        function xml2js($xmlnode) {
            $root = (func_num_args() > 1 ? false : true);
            $jsnode = array();
        
            if (!$root) {
                if (count($xmlnode->attributes()) > 0){
                    $jsnode["$"] = array();
                    foreach($xmlnode->attributes() as $key => $value)
                        $jsnode["$"][$key] = (string)$value;
                }
        
                $textcontent = trim((string)$xmlnode);
                if (count($textcontent) > 0)
                    $jsnode["_"] = $textcontent;
        
                foreach ($xmlnode->children() as $childxmlnode) {
                    $childname = $childxmlnode->getName();
                    if (!array_key_exists($childname, $jsnode))
                        $jsnode[$childname] = array();
                    array_push($jsnode[$childname], xml2js($childxmlnode, true));
                }
                return $jsnode;
            } else {
                $nodename = $xmlnode->getName();
                $jsnode[$nodename] = array();
                array_push($jsnode[$nodename], xml2js($xmlnode, true));
                return json_encode($jsnode);
            }
        }   
        

        用法示例:

        $xml = simplexml_load_file("myfile.xml");
        echo xml2js($xml);
        

        示例输入 (myfile.xml):

        <family name="Johnson">
            <child name="John" age="5">
                <toy status="old">Trooper</toy>
                <toy status="old">Ultrablock</toy>
                <toy status="new">Bike</toy>
            </child>
        </family>
        

        示例输出:

        {"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
        

        印刷精美:

        {
            "family" : [{
                    "$" : {
                        "name" : "Johnson"
                    },
                    "child" : [{
                            "$" : {
                                "name" : "John",
                                "age" : "5"
                            },
                            "toy" : [{
                                    "$" : {
                                        "status" : "old"
                                    },
                                    "_" : "Trooper"
                                }, {
                                    "$" : {
                                        "status" : "old"
                                    },
                                    "_" : "Ultrablock"
                                }, {
                                    "$" : {
                                        "status" : "new"
                                    },
                                    "_" : "Bike"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
        

        要记住的怪癖: 具有相同标记名的多个标记可以是兄弟。其他解决方案很可能会丢弃除最后一个兄弟之外的所有内容。为了避免这种情况,每个节点,即使它只有一个子节点,也是一个数组,它为标记名的每个实例保存一个对象。 (参见示例中的多个“”元素)

        即使是根元素(其应该只存在于有效的 XML 文档中)也存储为带有实例对象的数组,只是为了具有一致的数据结构。

        为了能够区分 XML 节点内容和 XML 属性,每个对象的属性都存储在“$”中,内容存储在“_”子级中。

        编辑: 我忘了显示您的示例输入数据的输出

        {
            "states" : [{
                    "state" : [{
                            "$" : {
                                "id" : "AL"
                            },
                            "name" : [{
                                    "_" : "Alabama"
                                }
                            ]
                        }, {
                            "$" : {
                                "id" : "AK"
                            },
                            "name" : [{
                                    "_" : "Alaska"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
        

        【讨论】:

        • 它可以解析大型 XML 数据吗?
        • 此解决方案更好,因为不会丢弃 XML 属性。还可以在xml.com/lpt/a/1658 了解为什么这种复杂结构比简化结构更好(请参阅“半结构化 XML”).... Ops,对于 CDATA,正如 @txyoji 建议将 CDATA 元素展平 $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA); 一样。
        • 非常感谢自定义函数!它使调整非常容易。顺便说一句,添加了一个以 JS 方式解析 XML 的函数的编辑版本:每个条目都有自己的对象(如果它们具有相同的标记名,则条目不会存储在单个数组中),因此保留了顺序。
        • 错误Fatal error: Uncaught Error: Call to a member function getName() on bool ..我认为php版本失败:-( ..请帮忙!
        【解决方案9】:

        尝试使用这个

        $xml = ... // Xml file data
        
        // first approach
        $Json = json_encode(simplexml_load_string($xml));
        
        ---------------- OR -----------------------
        
        // second approach
        $Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA));
        
        echo $Json;
        

        或者

        你可以使用这个库:https://github.com/rentpost/xml2array

        【讨论】:

          【解决方案10】:
          $templateData =  $_POST['data'];
          
          // initializing or creating array
          $template_info =  $templateData;
          
          // creating object of SimpleXMLElement
          $xml_template_info = new SimpleXMLElement("<?xml version=\"1.0\"?><template></template>");
          
          // function call to convert array to xml
          array_to_xml($template_info,$xml_template_info);
          
          //saving generated xml file
           $xml_template_info->asXML(dirname(__FILE__)."/manifest.xml") ;
          
          // function defination to convert array to xml
          function array_to_xml($template_info, &$xml_template_info) {
              foreach($template_info as $key => $value) {
                  if(is_array($value)) {
                      if(!is_numeric($key)){
                          $subnode = $xml_template_info->addChild($key);
                          if(is_array($value)){
                              $cont = 0;
                              foreach(array_keys($value) as $k){
                                  if(is_numeric($k)) $cont++;
                              }
                          }
          
                          if($cont>0){
                              for($i=0; $i < $cont; $i++){
                                  $subnode = $xml_body_info->addChild($key);
                                  array_to_xml($value[$i], $subnode);
                              }
                          }else{
                              $subnode = $xml_body_info->addChild($key);
                              array_to_xml($value, $subnode);
                          }
                      }
                      else{
                          array_to_xml($value, $xml_template_info);
                      }
                  }
                  else {
                      $xml_template_info->addChild($key,$value);
                  }
              }
          }
          

          【讨论】:

          • 这是一个基于数据数组的小型通用解决方案,可以是 JSON 转换的 json_decode ...lucky
          • 这如何回答原始问题?你的回答似乎比原来的问题更复杂,而且似乎也没有在任何地方提到 JSON。
          【解决方案11】:

          这里所有的解决方案都有问题!

          ... 当表示需要完美的 XML 解释(属性没有问题)并重现所有 text-tag-text-tag-text-... 和标签顺序时。还要记住这里JSON object“是一个无序集”(不重复键并且键不能具有预定义的顺序)......即使ZF's xml2json是错误的(!)因为没有完全保留XML结构。

          这里的所有解决方案都对这个简单的 XML 有问题,

              <states x-x='1'>
                  <state y="123">Alabama</state>
                  My name is <b>John</b> Doe
                  <state>Alaska</state>
              </states>
          

          ...@FTav 解决方案似乎比 3 行解决方案更好,但在使用此 XML 测试时也有小错误。

          旧解决方案是最好的(用于无损表示)

          这个解决方案,今天被称为 jsonML,被Zorba project 和其他人使用,并在~2006 年或~2007 年由(分别)Stephen McKamey 和@987654325 首次提出@。

          // the core algorithm is the XSLT of the "jsonML conventions"
          // see  https://github.com/mckamey/jsonml
          $xslt = 'https://raw.githubusercontent.com/mckamey/jsonml/master/jsonml.xslt';
          $dom = new DOMDocument;
          $dom->loadXML('
              <states x-x=\'1\'>
                  <state y="123">Alabama</state>
                  My name is <b>John</b> Doe
                  <state>Alaska</state>
              </states>
          ');
          if (!$dom) die("\nERROR!");
          $xslDoc = new DOMDocument();
          $xslDoc->load($xslt);
          $proc = new XSLTProcessor();
          $proc->importStylesheet($xslDoc);
          echo $proc->transformToXML($dom);
          

          生产

          ["states",{"x-x":"1"},
              "\n\t    ",
              ["state",{"y":"123"},"Alabama"],
              "\n\t\tMy name is ",
              ["b","John"],
              " Doe\n\t    ",
              ["state","Alaska"],
              "\n\t"
          ]
          

          http://jsonML.orggithub.com/mckamey/jsonml。这个 JSON 的产生规则是基于 element JSON-analog,

          这个语法是一个元素定义和重复,用
          element-list ::= element ',' element-list | element

          【讨论】:

          • 非常不寻常的 xml 结构,我怀疑在现实生活中会有用例。
          【解决方案12】:

          这是对 Antonio Max 最受好评的解决方案的改进,该解决方案也适用于具有名称空间的 XML(通过将冒号替换为下划线)。它还有一些额外的选项(并且可以正确解析&lt;person my-attribute='name'&gt;John&lt;/person&gt;)。

          function parse_xml_into_array($xml_string, $options = array()) {
              /*
              DESCRIPTION:
              - parse an XML string into an array
              INPUT:
              - $xml_string
              - $options : associative array with any of these keys:
                  - 'flatten_cdata' : set to true to flatten CDATA elements
                  - 'use_objects' : set to true to parse into objects instead of associative arrays
                  - 'convert_booleans' : set to true to cast string values 'true' and 'false' into booleans
              OUTPUT:
              - associative array
              */
          
              // Remove namespaces by replacing ":" with "_"
              if (preg_match_all("|</([\\w\\-]+):([\\w\\-]+)>|", $xml_string, $matches, PREG_SET_ORDER)) {
                  foreach ($matches as $match) {
                      $xml_string = str_replace('<'. $match[1] .':'. $match[2], '<'. $match[1] .'_'. $match[2], $xml_string);
                      $xml_string = str_replace('</'. $match[1] .':'. $match[2], '</'. $match[1] .'_'. $match[2], $xml_string);
                  }
              }
          
              $output = json_decode(json_encode(@simplexml_load_string($xml_string, 'SimpleXMLElement', ($options['flatten_cdata'] ? LIBXML_NOCDATA : 0))), ($options['use_objects'] ? false : true));
          
              // Cast string values "true" and "false" to booleans
              if ($options['convert_booleans']) {
                  $bool = function(&$item, $key) {
                      if (in_array($item, array('true', 'TRUE', 'True'), true)) {
                          $item = true;
                      } elseif (in_array($item, array('false', 'FALSE', 'False'), true)) {
                          $item = false;
                      }
                  };
                  array_walk_recursive($output, $bool);
              }
          
              return $output;
          }
          

          【讨论】:

          • 一个人不会使用 Regex 来解析 XML,除非它是一个结构简单且数据非常可预测的简单 XML。我不能强调这个解决方案有多糟糕。这会破坏数据。更不用说它非常慢(您使用正则表达式解析,然后再次重新解析?)并且不处理自闭合标签。
          • 我不认为你真的看过这个函数。它不使用正则表达式进行实际解析,仅作为处理命名空间的简单修复 - 这一直适用于我所有的 xml 案例 - 并且它正在工作是最重要的,而不是“政治正确”。不过,如果您愿意,欢迎您改进它!
          • 它对您有效并不意味着它是正确的。像这样的代码会产生非常难以诊断的错误,并产生漏洞利用。我的意思是,即使在像w3schools.com/xml/xml_elements.asp 这样的网站上从表面上看 XML 规范,也会显示很多为什么这个解决方案不起作用的原因。就像我说的,它无法检测到像&lt;element/&gt; 这样的自闭合标签,无法处理以下划线开头或包含下划线的元素,这在 XML 中是允许的。无法检测 CDATA。正如我所说,它很慢。由于内部解析,这是一个 O(n^2) 复杂度。
          • 问题是这里甚至没有问过如何处理命名空间,并且有一些正确的方法来处理命名空间。命名空间作为一种有用的结构存在,不能像那样被解析并变成任何合理的解析器都不会处理的可憎之物。你需要做的不是创造“2016 年最慢算法”奖的竞争者,而是做一些搜索,想出无数的实际解决方案,比如这个 stackoverflow.com/questions/16412047/… 和称之为改进?哇。
          【解决方案13】:

          优化 Antonio Max 答案:

          $xmlfile = 'yourfile.xml';
          $xmlparser = xml_parser_create();
          
          // open a file and read data
          $fp = fopen($xmlfile, 'r');
          //9999999 is the length which fread stops to read.
          $xmldata = fread($fp, 9999999);
          
          // converting to XML
          $xml = simplexml_load_string($xmldata, "SimpleXMLElement", LIBXML_NOCDATA);
          
          // converting to JSON
          $json = json_encode($xml);
          $array = json_decode($json,TRUE);
          

          【讨论】:

          • 我使用了这种方法,但是 JSON 是空的。 XML 有效。
          【解决方案14】:

          在研究了所有答案之后,我想出了一个解决方案,它可以很好地与我的跨浏览器(包括控制台/开发工具)的 JavaScript 函数配合使用:

          <?php
          
           // PHP Version 7.2.1 (Windows 10 x86)
          
           function json2xml( $domNode ) {
            foreach( $domNode -> childNodes as $node) {
             if ( $node -> hasChildNodes() ) { json2xml( $node ); }
             else {
              if ( $domNode -> hasAttributes() && strlen( $domNode -> nodeValue ) ) {
               $domNode -> setAttribute( "nodeValue", $node -> textContent );
               $node -> nodeValue = "";
              }
             }
            }
           }
          
           function jsonOut( $file ) {
            $dom = new DOMDocument();
            $dom -> loadXML( file_get_contents( $file ) );
            json2xml( $dom );
            header( 'Content-Type: application/json' );
            return str_replace( "@", "", json_encode( simplexml_load_string( $dom -> saveXML() ), JSON_PRETTY_PRINT ) );
           }
          
           $output = jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' );
          
           echo( $output );
          
           /*
            Or simply 
            echo( jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' ) );
           */
          
          ?>
          

          它基本上创建了一个新的 DOMDocument,将 XML 文件加载到其中,并遍历每个节点和子节点,获取数据/参数并将其导出为 JSON,而没有烦人的“@”符号。

          链接到XML 文件。

          【讨论】:

            【解决方案15】:

            此解决方案处理命名空间、属性,并通过重复元素产生一致的结果(始终在数组中,即使只出现一次)。 灵感来自ratfactor's sxiToArray()

            /**
             * <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
             * <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
             * <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root> 
             *   -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
             */
            function domNodesToArray(array $tags, \DOMXPath $xpath)
            {
                $tagNameToArr = [];
                foreach ($tags as $tag) {
                    $tagData = [];
                    $attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
                    $subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
                    foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
                        // the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
                        if ($tag->hasAttribute($nsNode->nodeName)) {
                            $attrs[] = $nsNode;
                        }
                    }
            
                    foreach ($attrs as $attr) {
                        $tagData[$attr->nodeName] = $attr->nodeValue;
                    }
                    if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
                        $text = $subTags[0]->nodeValue;
                    } elseif (count($subTags) === 0) {
                        $text = '';
                    } else {
                        // ignore whitespace (and any other text if any) between nodes
                        $isNotDomText = function($node){return !($node instanceof \DOMText);};
                        $realNodes = array_filter($subTags, $isNotDomText);
                        $subTagNameToArr = domNodesToArray($realNodes, $xpath);
                        $tagData = array_merge($tagData, $subTagNameToArr);
                        $text = null;
                    }
                    if (!is_null($text)) {
                        if ($attrs) {
                            if ($text) {
                                $tagData['_'] = $text;
                            }
                        } else {
                            $tagData = $text;
                        }
                    }
                    $keyName = $tag->nodeName;
                    $tagNameToArr[$keyName][] = $tagData;
                }
                return $tagNameToArr;
            }
            
            function xmlToArr(string $xml)
            {
                $doc = new \DOMDocument();
                $doc->loadXML($xml);
                $xpath = new \DOMXPath($doc);
                $tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
                return domNodesToArray($tags, $xpath);
            }
            

            例子:

            php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
            {"root":[{"a":"5","b":["6"]}]}
            

            【讨论】:

            • 这实际上适用于多命名空间的情况,比其他解决方案更好,为什么要投反对票...
            • 在尝试了数十种解决方案之后,这是唯一对我有用的解决方案,非常感谢!
            【解决方案16】:

            如果你是 ubuntu 用户安装 xml 阅读器(我有 php 5.6。如果你有其他请找到包并安装)

            sudo apt-get install php5.6-xml
            service apache2 restart
            
            $fileContents = file_get_contents('myDirPath/filename.xml');
            $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
            $fileContents = trim(str_replace('"', "'", $fileContents));
            $oldXml = $fileContents;
            $simpleXml = simplexml_load_string($fileContents);
            $json = json_encode($simpleXml);
            

            【讨论】:

              【解决方案17】:
              This is better solution
              
              $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);
              return $array;
              

              【讨论】:

                【解决方案18】:

                发现 FTav 的答案最有用,因为它非常可定制,但他的 xml2js 函数有一些缺陷。例如,如果子元素具有相同的标记名,它们都将存储在一个对象中,这意味着元素的顺序将不会被保留。在某些情况下,我们确实希望保持顺序,因此我们最好将每个元素的数据存储在单独的对象中:

                function xml2js($xmlnode) {
                    $jsnode = array();
                    $nodename = $xmlnode->getName();
                    $current_object = array();
                
                    if (count($xmlnode->attributes()) > 0) {
                        foreach($xmlnode->attributes() as $key => $value) {
                            $current_object[$key] = (string)$value;
                        }
                    }
                
                    $textcontent = trim((string)$xmlnode);
                    if (strlen($textcontent) > 0) {
                        $current_object["content"] = $textcontent;
                    }
                
                    if (count($xmlnode->children()) > 0) {
                        $current_object['children'] = array();
                        foreach ($xmlnode->children() as $childxmlnode) {
                            $childname = $childxmlnode->getName();
                            array_push($current_object['children'], xml2js($childxmlnode, true));
                        }
                    }
                
                    $jsnode[ $nodename ] = $current_object;
                    return $jsnode;
                }
                

                这是它的工作原理。初始xml结构:

                <some-tag some-attribute="value of some attribute">
                  <another-tag>With text</another-tag>
                  <surprise></surprise>
                  <another-tag>The last one</another-tag>
                </some-tag>
                

                结果 JSON:

                {
                    "some-tag": {
                        "some-attribute": "value of some attribute",
                        "children": [
                            {
                                "another-tag": {
                                    "content": "With text"
                                }
                            },
                            {
                                "surprise": []
                            },
                            {
                                "another-tag": {
                                    "content": "The last one"
                                }
                            }
                        ]
                    }
                }
                

                【讨论】:

                  【解决方案19】:

                  像魅力一样发挥作用的最佳解决方案

                  $fileContents= file_get_contents($url);
                  
                  $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
                  
                  $fileContents = trim(str_replace('"', "'", $fileContents));
                  
                  $simpleXml = simplexml_load_string($fileContents);
                  
                  //$json = json_encode($simpleXml); // Remove // if you want to store the result in $json variable
                  
                  echo '<pre>'.json_encode($simpleXml,JSON_PRETTY_PRINT).'</pre>';
                  

                  Source

                  【讨论】:

                    【解决方案20】:

                    如果你的 XML 是一个肥皂文件,你可以使用这个:

                    $xmlStr = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $xmlStr);
                    $xml = new SimpleXMLElement($xmlStr);
                    return json_encode($xml);
                    

                    【讨论】:

                      【解决方案21】:
                              $content = str_replace(array("\n", "\r", "\t"), '', $response);
                              $content = trim(str_replace('"', "'", $content));
                              $xml = simplexml_load_string($content);
                              $json = json_encode($xml);
                              return json_decode($json,TRUE);
                      

                      这对我有用

                      【讨论】:

                        【解决方案22】:

                        接受(安东尼奥的)回答,来自这样的来源:

                        <MyData>
                          <Level1 myRel="parent" myName="AAA">
                            <Level2 myRel="child1" myName="BBB">
                            <Level2 myRel="child2" myName="CCC">
                              ...
                        

                        你会得到这样的数组:

                          'Level1' =>
                          [
                              0 =>
                              [
                                  '@attributes' => 
                                  [
                                      'myRel' => 'parent'
                                      'myName'  => 'AAA'
                                  ],
                                  'Level2' => 
                                  [
                                      0 => 
                                      [
                                          '@attributes' => 
                                          [
                                              'myRel'  => 'child_1'
                                              'myName'   => 'BBB'
                                          ],
                        

                        因此,如果您想使用您选择的密钥(即 myName)拥有密钥配对数组(而不是 0 数字):

                          'Level1' =>
                          [
                              'AAA' =>
                              [
                                  '@attributes' => 
                                  [
                                      'myRel' => 'parent'
                                      'myName'  => 'AAA'
                                  ],
                                  'Level2' => 
                                  [
                                      'BBB' => 
                                      [
                                          '@attributes' => 
                                          [
                                              'myRel'  => 'child_1'
                                              'myName'   => 'BBB'
                                          ],
                        

                        然后使用xmlToArrayByKey($xmlContent, 'myName')。代码在这里:

                        public function xmlToArrayByKey($content, $keyName)
                        {
                            try
                            {
                                $xml = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA );
                                $array= json_decode( json_encode($xml), TRUE);
                                return $this->xmlSetChild($array, $keyName);
                            } catch (Exception $ex) {
                                return ['xmlerror'=>$ex];
                            }
                        }
                        
                        public function xmlSetChild($array, $keyName, $step=0)
                        {
                            $new_array= [];
                            foreach ($array as $key_1=>$value_1)
                            {
                                if (is_array($value_1) && isset($value_1[0]))
                                {
                                    foreach ($value_1 as $idx=>$value_2)
                                    {
                                        $keyValue = $value_2['@attributes'][$keyName];
                                        $new_array[$key_1][$keyValue] = $this->xmlSetChild($value_2, $keyName, $step+1);
                                    }
                                }
                                else{
                                    $new_array[$key_1]=$value_1;
                                }
                            }
                            return $new_array;
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 2012-02-02
                          • 1970-01-01
                          • 1970-01-01
                          • 2017-11-04
                          • 2013-05-09
                          • 2021-11-25
                          • 2021-07-01
                          • 2018-07-30
                          相关资源
                          最近更新 更多