【问题标题】:Get the same results from SimpleXML as json_decode in PHP从 SimpleXML 获得与 PHP 中的 json_decode 相同的结果
【发布时间】:2014-02-28 15:28:35
【问题描述】:

我正在尝试将配置文件加载为 XML 或 JSON。我知道这是在重新发明轮子,但我正在尝试习惯一些我从未使用过的模式。

我的问题是我想不出一种方法来通知 SimpleXML_Load_File 当元素仅出现 1 次时,该元素应被视为数组而不是对象。

考虑以下 JSON:

{
    "database" : 
    {
        "name" : "MyDB",
        "driver" : "MySQL",
        "table" : 
        [
            {
                "name" : "user",
                "engine" : "MyISAM",
                "column" : 
                [
                    {
                        "name" : "username",
                        "type" : "varchar",
                        "size" : "25"
                    },
                    {
                        "name" : "password",
                        "type" : "varchar",
                        "size" : "60"
                    }
                 ]
              }
          ]
      }
  }

以及相关的XML:

<config>
    <database>
        <name>MyDB</name>
        <driver>MySQL</driver>
        <table>
            <name>user</name>
            <engine>MyISAM</engine>
            <column>
                <name>username</name>
                <type>varchar</type>
                <size>25</size>
            </column>
            <column>
                <name>password</name>
                <type>varchar</type>
                <size>60</size>
            </column>
        </table>
    </database>
</config>

除了&lt;config&gt; 元素之外,这些配置是相同的——由于SimpleXML 处理根级别元素的方式,我添加了它。

对于 JSON,您使用 [ ] 指定一个数组,json_decode 将使相应的元素成为一个对象数组(例如 table) - 但是对于 XML,我无法做到这一点告诉 - 这个例子中SimpleXML_Load_File 的结果是table 将是一个对象,而不是json_decode 返回的预期(我)的对象数组

我觉得我可能必须对应该是数组而不是对象的元素进行类型测试和转换,但我也觉得这可能会变得非常混乱。

这是用于加载这些文件的相关代码:

<?php $config_xml = simplexml_load_file( 'database.config.xml' ); ?>
<?php $config_json = json_decode( file_get_contents('database.config.json'), false ); ?>

结果:

$config_xml-&gt;database-&gt;table - 对象

$config_json-&gt;database-&gt;table - 对象数组

【问题讨论】:

  • 这并不像您想象的那么简单。 SimpleXMLElement 如何转换为 JSON 以及如何修改我在一篇由三部分组成的博客文章中概述的内容:SimpleXML and JSON Encode in PHP – Part I。如果您阅读了第一部分和第二部分,您可能能够更好地理解第三部分,它广泛地展示了如何更改 XML 的 JSON 表示。但是,我不太确定您尝试做的事情是否可以以一般方式进行。最有可能...
  • ...然后您的代码包含您想要作为数组的元素名称的“幻数”。

标签: php xml arrays json object


【解决方案1】:

两件事:

  • 扩展 S Korolevs 的回答:没有办法在 XML 中使用“匿名”数组。事实上,严格来说,XML 中没有数组本身,只有元素只允许(通过模式或约定)具有特殊的其他元素作为子元素。顺便说一句,您会遇到与列相同的问题
  • SimpleXML 是一种奇怪的野兽,我发现它很难调试和检查(至少 xdebug 在遍历子节点甚至显示属性方面有些麻烦)。 在您的情况下需要注意的重要一点是 SimpleXML Element 始终是一个对象,而不是一个数组。它“只是”实现了数组访问接口,因此您可以使用$element-&gt;children[0] 获取子节点。

好的,第三件事或更好的结论:

你得到不同的配置对象不是因为源结构,而是因为你使用了不同的解析器。 json_decode返回stdClass的对象,simplexml_load_file返回SimpleXMLElement的对象

【讨论】:

  • 你们俩说的都有道理。我确实了解当前使用的 XML 格式的限制。您愿意推荐一个可以使用 XSD 作为指导的不同解析库吗?我想我可能采取的方法是重组两个输出以符合单个预期输出。我试图保持简单,希望能够按原样使用每个创建的对象。
  • DOMDocument 类可以针对 XML 模式进行验证,但我认为它不会构建输出 (us2.php.net/manual/de/domdocument.schemavalidate.php)。重组的一个想法是:使用&lt;tables&gt;&lt;table 元素作为xml 中的“数组”,并使用tables 而不是table 作为JSON 中的键,这样您就可以在这两种情况下使用$object-&gt;tables[0]。另一个想法:看看 ZendFramework 1 的 ini 阅读器模块,他们有 xml 和其他一些格式的解析器
【解决方案2】:

当然,在你的 XML table 中代表的是一个对象。 XML 中的数组是这样的:

<tables>
    <table>
            <name>user</name>
            <engine>MyISAM</engine>
            <column>
...
            </column>
            <column>
...
            </column>
     </table>
     <table>
     ...
     </table>
</tables>

因此,tablestable 项的数组。我看到的问题是 JSON 和 XML 对象的结构在这种情况下会有所不同。

【讨论】:

  • 我测试的第一件事是添加一个空的&lt;table&gt;&lt;/table&gt; 元素,结果符合我的预期。我试图避免必须始终包含一个空元素集。如果能够使用 XSD 模式文件之类的东西来指导生成的对象,那就太好了。
  • 是的 - 对象的结构会有所不同 - 这是我试图避免或纠正的确切问题。
猜你喜欢
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
相关资源
最近更新 更多