V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NEETLEE
V2EX  ›  PHP

PHP 里如何实现数组转 xml 并且格式化

  •  
  •   NEETLEE · 2018-05-15 10:16:28 +08:00 · 2606 次点击
    这是一个创建于 2386 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,最近在琢磨 php 里把数组转换为 xml 格式的字符串并且支持格式化,昨天搞了一晚上,效果始终不理想。 今天来向各位大佬求助。 我这里贴一个我随便写的数组

    $arr = [
      'arr1' => 'asdfasdfewrsdfwer',
      'arr2' => [
        'arr3' => [
          'asdfasdf' => 123213,
        ],
        'arr4' => '123123sdfsdf',
        'arr5' => [
          'arr6' => [
            'arr7' => [
              'arr8' => [
                '123123',
                'sadfsdf',
                'aserwer53453',
                'asdfwetrxcverwt',
              ],
            ],
          ],
        ],
      ],
    ];
    

    再贴一下我写的存在问题的方法

    /**

    • 数组转换为 xml 格式的字符串
    • @param array $arr 需要转换的数组
    • @param boolean $format 是否格式化
    • @return string xml 格式的字符串 */

      $xml = '';
      foreach ($arr as $key => $value) {
        $xml .= "<$key>";
        if (is_array($value)) {
          $deep++;
          if ($format) {
            $xml .= PHP_EOL;
            $xml .= str_pad('', $deep * 2, ' ');
          }
          $xml .= arrayToXml($value, $format, $deep);
          $xml .= "</$key>";
        } else {
          $xml .= $value;
          $xml .= "</$key>";
        }
        if ($format) {
          $xml .= PHP_EOL;
          $next = next($arr);
          prev($arr);
          if ($next == false || is_array($next)) {
            $xml .= str_pad('', ($deep - 1) * 2, ' ');
          } else {
            $xml .= str_pad('', $deep * 2, ' ');
          }
          echo is_array($next) ? ' arr ' : $next;
          unset($next);
        }
        next($arr);
      }
      return $xml;
    }
    
    第 1 条附言  ·  2018-05-15 13:57:42 +08:00

    这是讨论的结果,感觉有待改进,暂时贴在这里,有空了再来完善吧

    • 将数组转成xml并格式化输出
    • @param array $arr 需要转换的数组
    • @param string $xml 调用时不需要传
    • @param integer $deep 调用时不需要传
    • @return string 转换的xml

    function arrayConvertXml($arr, $xml = '', $deep = 1) {
      if (!is_array($arr)) {
        return null;
      }
      foreach ($arr as $key => $value) {
        if (is_array($value)) {
          if ($deep > 1) {
            $xml .= str_pad('', ($deep - 1) * 2, ' ');
          }
          $xml .= "<$key>" . PHP_EOL;
          $xml = arrayConvertXml($value, $xml, $deep + 1);
          if ($deep > 1) {
            $xml .= str_pad('', ($deep - 1) * 2, ' ');
          }
          $xml .= "</$key>" . PHP_EOL;
        } else {
          $xml .= str_pad('', ($deep - 1) * 2, ' ');
          $xml .= "<$key>" . $value . "</$key>" . PHP_EOL;
        }
      }
      return $xml;
    }
    
    13 条回复    2018-05-15 14:36:44 +08:00
    NEETLEE
        1
    NEETLEE  
    OP
       2018-05-15 10:19:46 +08:00
    /**
    * 数组转换为 xml 格式的字符串
    * @param array $arr 需要转换的数组
    * @param boolean $format 是否格式化
    * @return string xml 格式的字符串
    */
    function arrayToXml($arr, $format = false, $deep = 0) {
    $xml = '';
    foreach ($arr as $key => $value) {
    $xml .= "<$key>";
    if (is_array($value)) {
    $deep++;
    if ($format) {
    $xml .= PHP_EOL;
    $xml .= str_pad('', $deep * 2, ' ');
    }
    $xml .= arrayToXml($value, $format, $deep);
    $xml .= "</$key>";
    } else {
    $xml .= $value;
    $xml .= "</$key>";
    }
    if ($format) {
    $xml .= PHP_EOL;
    $next = next($arr);
    prev($arr);
    if ($next == false || is_array($next)) {
    $xml .= str_pad('', ($deep - 1) * 2, ' ');
    } else {
    $xml .= str_pad('', $deep * 2, ' ');
    }
    unset($next);
    }
    next($arr);
    }
    return $xml;
    }


    这是方法,不知道怎么的题目里方法名被干掉了...
    KomeijiSatori
        2
    KomeijiSatori  
       2018-05-15 10:22:20 +08:00   ❤️ 1
    Chappako
        3
    Chappako  
       2018-05-15 10:23:18 +08:00   ❤️ 1
    littleylv
        4
    littleylv  
       2018-05-15 10:26:09 +08:00
    楼主如果出于研究学习的目的,挺好。
    如果是为了解决实际问题,需要搞一晚上? Gayhub 搜一下,轮子一大堆。

    请善用搜索!
    InternetExplorer
        5
    InternetExplorer  
       2018-05-15 10:32:14 +08:00   ❤️ 1
    有个叫 SimpleXMLElement 东西 了解一下 http://php.net/manual/en/simplexml.examples-basic.php#example-6636
    imcnan
        6
    imcnan  
       2018-05-15 10:35:43 +08:00   ❤️ 1
    ```php

    public function arrayToXML($arr) {

    $xml = "<xml>";
    foreach ($arr as $key => $val) {
    $node = "";
    if ( is_string($val) || is_int($val) || is_double($val) || is_float($val) ) {
    $val = htmlspecialchars($val);
    $node = "<{$key}>{$val}</{$key}>";
    } else if (is_array(val)) {
    die("不应该有这个参数的");
    }
    $xml .= $node;
    $xml .= "\n";
    }
    $xml .= "</xml>";
    return $xml;
    }

    private function xmlToArray($xml) {

    /*
    <xml><return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[OK]]></return_msg>
    <appid><![CDATA[wx2949f84b5ee561e9]]></appid>
    <mch_id><![CDATA[1502705451]]></mch_id>
    <nonce_str><![CDATA[YfEbfNE0xdUjJPAK]]></nonce_str>
    <sign><![CDATA[5084033CADE92C9C32798406C3D5C82F]]></sign>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <prepay_id><![CDATA[wx241217030922516345c975b91289464085]]></prepay_id>
    <trade_type><![CDATA[JSAPI]]></trade_type>
    </xml>
    */
    $ret = array();

    $parser = xml_parser_create("UTF-8");
    $values = array();
    $keys = array();
    xml_parse_into_struct($parser, $xml, $values, $keys);

    foreach ($keys as $nodeName => $val) {
    $id = $val[0];
    if (!empty($values[$id]["value"])) {
    $nodeName = strtoupper($nodeName);
    $ret[$nodeName] = $values[$id]["value"];
    }
    }

    return $ret;
    }

    ```
    msg7086
        7
    msg7086  
       2018-05-15 10:43:12 +08:00
    字符串手拼 XML ?
    和我们用 grep+awk 解析 XML 的程序员有得一拼啊。

    你要自己做 XML 转换,请从头写一个 XML 库。
    NEETLEE
        8
    NEETLEE  
    OP
       2018-05-15 11:02:27 +08:00
    @littleylv
    @msg7086
    确实是拍脑门的想法,突然就想研究一下,反正下班了也没事,哈哈哈
    NEETLEE
        9
    NEETLEE  
    OP
       2018-05-15 12:35:34 +08:00
    /**
    * 将数组转成 xml
    * @param array $arr 需要转换的数组
    * @return string 转换的 xml
    */
    function arrayConvertXml($arr, $xml = '', $deep = 1) {
    if (!is_array($arr)) {
    return null;
    }
    foreach ($arr as $key => $value) {
    if (is_array($value)) {
    if ($deep > 1) {
    $xml .= str_pad('', ($deep - 1) * 2, ' ');
    }
    $xml .= "<$key>" . PHP_EOL;
    $xml = arrayConvertXml($value, $xml, $deep + 1);
    if ($deep > 1) {
    $xml .= str_pad('', ($deep - 1) * 2, ' ');
    }
    $xml .= "</$key>" . PHP_EOL;
    } else {
    $xml .= str_pad('', ($deep - 1) * 2, ' ');
    $xml .= "<$key>" . $value . "</$key>" . PHP_EOL;
    }
    }
    return $xml;
    }

    和同事讨论了一下,最后得出如上函数,基本上没有问题了
    msg7086
        10
    msg7086  
       2018-05-15 12:59:45 +08:00
    key 的转译没有,value 的转译也没有,随便来个特殊字符就崩了。
    fuxkcsdn
        11
    fuxkcsdn  
       2018-05-15 13:23:30 +08:00 via iPhone
    NEETLEE
        12
    NEETLEE  
    OP
       2018-05-15 13:36:09 +08:00
    @msg7086 你是说<mch_id><![CDATA[1502705451]]></mch_id>这样的格式吗
    msg7086
        13
    msg7086  
       2018-05-15 14:36:44 +08:00
    @NEETLEE 有很多转译方法……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5010 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 03:59 · PVG 11:59 · LAX 19:59 · JFK 22:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.