【问题标题】:How can I preserve the "tag order" when converting an XML fragment to an array in PHP?在 PHP 中将 XML 片段转换为数组时如何保留“标签顺序”?
【发布时间】:2012-09-14 01:45:17
【问题描述】:

我已经阅读了大量关于在 PHP 中将 XML 文档或片段转换为数组的文章和 Stack Overflow 问题,但到目前为止我所阅读的都没有解决我的具体问题。这是我的困境,前面是一个示例 XML 片段:

<category>
  <template>
    <random>
      <li>And a good</li>
      <li>Pleasant</li>
      <li>Good</li>
      <li>Fantabulous</li>
    </random>
    <set name="TOD"><srai>time of day</srai></set> to you, <get name="name" />.
    <random>
      <li>How are you?</li>
      <li>To what do I owe the pleasure of this visit?</li>
      <li>May your Athlete's Foot be under control, and may the flying monkeys never come to take your dog!</li>
      <li>I trust your <get name="TOD" /> is going well?</li>
      <li>May your <get name="TOD" /> be as pleasant as possible.</li>
    </random>
  </template>
</category>

这是我的脚本将要处理的一些 XML 的真实示例。需要保留 XML 标记的顺序,因为解析结果需要正确连接以提供正确的结果。到目前为止,所有将 XML 片段转换为数组的方法都创建了不再包含正确顺序的数组。例如,这里是上述 XML 的 var 转储,一旦它被转换为数组:

Template array Var Dump: 
array(4) {
  ["random"]=>
  array(2) {
    [0]=>
    array(1) {
      ["li"]=>
      array(4) {
        [0]=>
        array(1) {
          ["text"]=>
          string(10) "And a good"
        }
        [1]=>
        array(1) {
          ["text"]=>
          string(8) "Pleasant"
        }
        [2]=>
        array(1) {
          ["text"]=>
          string(4) "Good"
        }
        [3]=>
        array(1) {
          ["text"]=>
          string(11) "Fantabulous"
        }
      }
    }
    [1]=>
    array(1) {
      ["li"]=>
      array(5) {
        [0]=>
        array(1) {
          ["text"]=>
          string(12) "How are you?"
        }
        [1]=>
        array(1) {
          ["text"]=>
          string(44) "To what do I owe the pleasure of this visit?"
        }
        [2]=>
        array(1) {
          ["text"]=>
          string(97) "May your Athlete's Foot be under control, and may the flying monkeys never come to take your dog!"
        }
        [3]=>
        array(2) {
          ["text"]=>
          array(2) {
            [0]=>
            string(12) "I trust your"
            [1]=>
            string(14) "is going well?"
          }
          ["get"]=>
          array(1) {
            ["@attributes"]=>
            array(1) {
              ["name"]=>
              string(3) "TOD"
            }
          }
        }
        [4]=>
        array(2) {
          ["text"]=>
          array(2) {
            [0]=>
            string(8) "May your"
            [1]=>
            string(27) "be as pleasant as possible."
          }
          ["get"]=>
          array(1) {
            ["@attributes"]=>
            array(1) {
              ["name"]=>
              string(3) "TOD"
            }
          }
        }
      }
    }
  }
  ["set"]=>
  array(2) {
    ["@attributes"]=>
    array(1) {
      ["name"]=>
      string(3) "TOD"
    }
    ["srai"]=>
    array(1) {
      ["text"]=>
      string(11) "time of day"
    }
  }
  ["text"]=>
  array(2) {
    [0]=>
    string(7) "to you,"
    [1]=>
    string(1) "."
  }
  ["get"]=>
  array(1) {
    ["@attributes"]=>
    array(1) {
      ["name"]=>
      string(4) "name"
    }
  }
}

可以看出,数组在创建时“丢失”了 XML 片段的顺序,并且您无法以线性方式遍历数组以获得正确的响应。这是我的问题的症结所在,也是我想要“解决”的问题。

我在此示例中使用的方法是 json_decode(json_encode($xml), true),但我使用了其他更复杂的脚本函数,结果几乎相同。那么,正如我在这篇文章的标题中所问的那样,在 PHP 中将 XML 片段转换为数组时如何保持“标签顺序”?

【问题讨论】:

  • 那么JSON指定key是无序的,所以很明显,如果你把它变成JSON的话,顺序会丢失。
  • 我没有意识到这一点,尽管我在几篇文章中读到 JSON 仍然被认为是“正在进行的工作”,所以也许有改进的希望。 :)

标签: php xml


【解决方案1】:

很确定没有可用的标志,比如simpleXMLjson_decode。我不认为 XML 旨在保留这一点。该结构并非旨在传达这一点,可以看到它如何导致糟糕的设计。对于 XML,您可以通过在 XSD 中使用 sequence 来解决此问题。但您的数据看起来更像 DOM。

作为一种解决方法,您是否考虑过将其解析为 DOM Document 并单步执行?没有太多代码可以自己利用它来解析它。

【讨论】:

  • 我不确定您指的是哪个“标志”,除非它是我在最后发布的代码中的“真实”标志(例如 json_decode(json_encode($xml), true) )。该特定标志确保该函数返回一个数组,而不是一个对象。至于使用DOM Document,我尝试了几种不同的方法来实现我的目标,但似乎代码比我认为有效的要多得多。也许我只是被宠坏了,期待太多? :)
  • 是的,我是说如果你没有按原样得到它,我不知道有什么东西可以启用这种行为。我认为一个好的 XML 解析器应该保留元素的自然顺序。我猜想 LibXML 会(但默认情况下不会使用 PHP?)。认为您需要使用 DOMDocument 编写自己的递归解析方法。
  • 事实上,我最终不得不这样做。该脚本是一个“弗兰肯斯坦的怪物”,由 SimpleXMLElement 和 SimpleXMLIterator 对象、一些针对某些特定元素的“廉价和肮脏”的数组转换以及检测混合内容并将“未标记”内容包装在 中的“快速修复”功能组成标签,基本上将&lt;mixed&gt;some text &lt;tag name="here" /&gt; and more text&lt;/mixed&gt; 更改为&lt;mixed&gt;&lt;text&gt;some text &lt;/text&gt;&lt;tag name="here" /&gt;&lt;text&gt; and more text&lt;/text&gt;&lt;/mixed&gt;。总的来说,剧本就像一只斗牛犬;它太丑了,太可爱了。 :)
  • 那里也没有preg? :)
  • 不,正则表达式和我自己相处不来。但是,有几行 str_replace() 行。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 2021-08-31
  • 1970-01-01
  • 2020-04-08
  • 2012-05-05
  • 2017-09-04
相关资源
最近更新 更多