【问题标题】:Passing PHP associative arrays to and from XML将 PHP 关联数组传入和传出 XML
【发布时间】:2010-09-11 02:11:33
【问题描述】:

有没有一种简单的方法可以将 PHP 关联数组与 XML 进行编组?例如,我有以下数组:

$items = array("1", "2",
    array(
        "item3.1" => "3.1",
        "item3.2" => "3.2"
        "isawesome" => true
    )
);

如何以尽可能少的行将其转换为类似于以下 XML 的内容,然后再返回?

<items>
    <item>1</item>
    <item>2</item>
    <item>
        <item3_1>3.1</item3_1>
        <item3_2>3.2</item3_2>
        <isawesome>true</isawesome>
    </item>
</items>

我真的不在乎是否必须稍微更改数组结构,或者输出的 XML 是否与上面的示例不同。我一直在尝试使用 PHP 的 XMLReaderXMLWriter,但是文档太差了,因此我生成的代码看起来不像我认为的那样:

$xml = SomeXMLWriter::writeArrayToXml($items);
$array = SomeXMLWriter::writeXmlToArray($xml);

在不编写我自己的自定义类的情况下获得 PHP 数组的基本原始 XML 转储真的比这更难吗?

我尽量避免使用 PEAR。除了我在使用它时遇到的配置问题之外,我从来没有使用过我曾经使用过的任何软件包。

【问题讨论】:

    标签: php xml xml-serialization


    【解决方案1】:

    SimpleXML 非常适合您使用。

    【讨论】:

      【解决方案2】:

      对于那些不使用 PEAR 包但已安装 PHP5 的人。这对我有用:

      /**
       * Build A XML Data Set
       *
       * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
       * @param string $startElement Root Opening Tag, default fx_request
       * @param string $xml_version XML Version, default 1.0
       * @param string $xml_encoding XML Encoding, default UTF-8
       * @return string XML String containig values
       * @return mixed Boolean false on failure, string XML result on success
       */
      public function buildXMLData($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8') {
          if(!is_array($data)) {
              $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
              trigger_error($err);
              if($this->_debug) echo $err;
              return false; //return false error occurred
          }
          $xml = new XmlWriter();
          $xml->openMemory();
          $xml->startDocument($xml_version, $xml_encoding);
          $xml->startElement($startElement);
      
          /**
           * Write XML as per Associative Array
           * @param object $xml XMLWriter Object
           * @param array $data Associative Data Array
           */
           function write(XMLWriter $xml, $data) {
               foreach($data as $key => $value) {
                   if(is_array($value)) {
                       $xml->startElement($key);
                       write($xml, $value);
                       $xml->endElement();
                       continue;
                   }
                   $xml->writeElement($key, $value);
               }
           }
           write($xml, $data);
      
           $xml->endElement();//write end element
           //Return the XML results
           return $xml->outputMemory(true); 
      }
      

      【讨论】:

      • 如果你的数据中有非关联数组(或者更确切地说,数组键中有数字),添加一个'if (is_numeric($key)) $key = "item";'在 foreach 块的开头(在 is_array 之前)就可以了。
      • 为了也能处理数值数组,添加$fKey = is_numeric($key) ? 'numericValue' : $key; before if(is_array($value)) 语句,并在foreach 语句的其余部分使用$fKey
      • 哦@VassilisGr,我在那里做了类似的事情:if(is_numeric($key)) { $key = 'node'; } 并将function write 移到外面,你不能声明两次相同的函数,但@Conrad 现在会这样做。 (该死,我现在看到@disq 评论哈哈)
      【解决方案3】:

      我也遇到过一些同样的问题,所以我创建了两个类:

      bXml

      扩展 SimpleXml 并纠正其存在的一些问题的类。就像无法添加 CData 节点或 Comment 节点一样。我还添加了一些附加功能,例如使用 php 流功能添加子节点 $oXml-&gt;AddChild("file:///user/data.xml") 或添加 XML 字符串子节点,如 $oXml-&gt;AddChild("&lt;more&gt;&lt;xml&gt;yes&lt;/xml&gt;&lt;/more&gt;");,但基本上我只是想修复 simpleXML 问题。

      bArray

      我扩展了 ArrayObject 类,以便所有数组功能都可以面向对象且一致,因此您无需记住 array_walk 通过引用对数组进行操作,而 array_filter 通过值对数组进行操作。因此,您可以执行$oArray-&gt;flip()-&gt;Reverse()-&gt;Walk(/*callback*/); 之类的操作,然后仍以您通常希望$oArray[key] 的方式访问该值。

      这两种方法都将自身输出为数组和 Xml,因此您可以在它们之间无缝跳转。所以你可以$oXml-&gt;AsArray();$oArray-&gt;AsXml(); 我发现这样做比在array2xml 或xml2array 方法之间不断地来回传递东西更容易。

      http://code.google.com/p/blibrary/source

      这两个类都可以被覆盖以创建您选择的自定义类,并且可以彼此独立使用。

      【讨论】:

      • 扩展 SimpleXML 来做到这一点是一个非常好的主意!
      【解决方案4】:
      class Xml {
      
          public static function from_array($arr, $xml = NULL)
          {
              $first = $xml;
              if($xml === NULL) $xml = new SimpleXMLElement('<root/>');
              foreach ($arr as $k => $v) 
              {
                  is_array($v)
                      ? self::from_array($v, $xml->addChild($k))
                      : $xml->addChild($k, $v);
              }
              return ($first === NULL) ? $xml->asXML() : $xml;
          }
      
          public static function to_array($xml)
          {
              $xml = simplexml_load_string($xml);
              $json = json_encode($xml);
              return json_decode($json,TRUE);
          }
      
      }
      
      $xml = xml::from_array($array);
      $array = xml::to_array($xml);
      

      【讨论】:

        【解决方案5】:

        一般尝试 Zend_Config 和 Zend Framework。

        我想这将是一个两步过程:数组到 Zend_Config,Zend_Config 到 XML。

        【讨论】:

          【解决方案6】:

          听起来像是 SimpleXML 的工作。

          我会建议一个稍微不同的 XML 结构..

          想知道为什么需要从数组转换 -> XML 并返回。如果您可以按照您所说的修改数组结构,为什么不直接生成 XML 呢?如果已经存在采用该数组配置的某些代码,只需修改它以接受 XML。然后你有1种数据格式/输入类型,根本不需要转换..

          <items>
            <item id="1"/>
            <item id="2"/>
            <item id="3">
            <subitems>     
              <item id="3.1"/>
              <item id="3.2" isawesome="true"/>
            </subitems>
            </item>
          </items>
          

          【讨论】:

            【解决方案7】:

            这是我编写的一个函数,用于获取 XML 并将其转换为 PHP 关联数组。一个警告是 id 当前不处理属性或 c 数据。虽然它会通过将重复的 XML 标签放入以标签命名的数组中来处理同一级别的重复 XML 标签。

            
            <?php
            
            $xml_req1 = <<<XML
            <?xml version="1.0"?>
            <Vastera:CustomerValidation_RequestInfo
                  xmlns:Vastera="http://ndc-ah-prd.am.mot.com:10653/MotVastera_CustomerValidation/MC000078/Docs/">
              <PartnerID>5550000100-003</PartnerID>
              <PartnerType>PTNR_INTER_CONSIGNEE</PartnerType>
              <OperatingUnit>100</OperatingUnit>
              <Status>ACTIVE</Status>
              <CustomerSeqNumber>111</CustomerSeqNumber>
              <CustomerName>Greg Co</CustomerName>
              <Address1>123 Any Ln</Address1>
              <Address2>?</Address2>
              <Address3>?</Address3>
              <Address4>?</Address4>
              <Address5>?</Address5>
              <City>Someplace</City>
              <PostalCode>603021</PostalCode>
              <State>CA</State>
              <CountryCode>US</CountryCode>
              <TaxReference>222</TaxReference>
              <PartyRelated>Y</PartyRelated>
              <BusinessUnit>GSBU</BusinessUnit>
              <Region>GSRGN</Region>
              <LocationName>DBA Mac Head Computing</LocationName>
              <LoadOnly>N</LoadOnly>
              <VSTM>333</VSTM>
              <MilitaryCustomerFlag>Y</MilitaryCustomerFlag>
              <USFederalGovernmentCustomer>Y</USFederalGovernmentCustomer>
              <Non-USGovernmentCustomer>Y</Non-USGovernmentCustomer>
              <Vastera:EPCIActivity>
                <EPCIActivityNuclearCode>NUCLEAR</EPCIActivityNuclearCode>
                <EPCIActivityNuclearValue>N</EPCIActivityNuclearValue>
                <EPCIActivityNuclearApproveDate>2011-05-16:07:19:37</EPCIActivityNuclearApproveDate>
                <EPCIActivityNuclearExpireDate>2056-12-31:12:00:00</EPCIActivityNuclearExpireDate>
                <EPCIActivityNuclearCountry>US</EPCIActivityNuclearCountry>
                <EPCIActivityChemBioCode>CHEM_BIO</EPCIActivityChemBioCode>
                <EPCIActivityChemBioValue>N</EPCIActivityChemBioValue>
                <EPCIActivityChemBioApproveDate>2011-05-16:07:19:37</EPCIActivityChemBioApproveDate>
                <EPCIActivityChemBioExpireDate>2056-12-31:12:00:00</EPCIActivityChemBioExpireDate>
                <EPCIActivityChemBioCountry>US</EPCIActivityChemBioCountry>
                <EPCIActivityMissileCode>MISSILE</EPCIActivityMissileCode>
                <EPCIActivityMissileValue>N</EPCIActivityMissileValue>
                <EPCIActivityMissileApproveDate>2011-05-16:07:19:37</EPCIActivityMissileApproveDate>
                <EPCIActivityMissileExpireDate>2056-12-31:12:00:00</EPCIActivityMissileExpireDate>
                <EPCIActivityMissileCountry>US</EPCIActivityMissileCountry>
              </Vastera:EPCIActivity>
              <SourceSystem>GSB2BSS</SourceSystem>
              <CreatedDate>2011-05-16:07:18:55</CreatedDate>
              <CreatedBy>c18530</CreatedBy>
              <LastModifiedDate>2011-05-16:07:18:55</LastModifiedDate>
              <LastModifiedBy>c18530</LastModifiedBy>
              <ContactName>Greg, "Da Man" Skluacek</ContactName>
              <ContactTitle>Head Honcho</ContactTitle>
              <ContactPhone>555-555-5555</ContactPhone>
              <ContactFax>666-666-6666</ContactFax>
              <ContactEmail>gskluzacek@gregco.com</ContactEmail>
              <ContactWeb>www.gregco.com</ContactWeb>
            </Vastera:CustomerValidation_RequestInfo>
            XML;
            
            $xml_req2 = <<<XML
            <?xml version="1.0"?>
            <order>
                <orderNumber>123</orderNumber>
                <customerAddress>
                    <type>Ship To</type>
                    <name>Bob McFly</name>
                    <addr1>123 Lincoln St</addr1>
                    <city>Chicago</city>
                    <state>IL</state>
                    <zip>60001</zip>
                </customerAddress>
                <customerAddress>
                    <type>Bill To</type>
                    <name>McFly Products Inc.</name>
                    <addr1>P.O. Box 6695</addr1>
                    <city>New York</city>
                    <state>NY</state>
                    <zip>99081-6695</zip>
                </customerAddress>
                <item>
                    <line>1</line>
                    <part>123001A</part>
                    <qty>5</qty>
                    <price>10.25</price>
                </item>
                <item>
                    <line>2</line>
                    <part>456002B</part>
                    <qty>3</qty>
                    <price>20.50</price>
                </item>
                <item>
                    <line>3</line>
                    <part>789003C</part>
                    <qty>1</qty>
                    <price>41.00</price>
                </item>
                <orderSubTotal>133.25</orderSubTotal>
                <tax>6.66</tax>
                <shipping>10.00</shipping>
                <orderTotal>149.91</orderTotal>
            </order>
            XML;
            
            $doc = new DOMDocument();
            $doc->preserveWhiteSpace = false;
            $doc->loadXML($xml_req1);
            
            $arr = xml_to_arr($doc->documentElement);
            
            print "\n\n----\n\n";
            
            print_r($arr);
            
            print "\n\n----\n\n";
            
            $doc2 = new DOMDocument();
            $doc2->preserveWhiteSpace = false;
            $doc2->loadXML($xml_req2);
            
            $arr2 = xml_to_arr($doc2->documentElement);
            
            print "\n\n----\n\n";
            
            print_r($arr2);
            
            print "\n\n----\n\n";
            
            exit;
            
            function xml_to_arr($curr_node) {
                $val_array = array();
                $typ_array = array();
            
                foreach($curr_node->childNodes as $node) {
                    if ($node->nodeType == XML_ELEMENT_NODE) {
            
                        $val = xml_to_arr($node);
            
                        if (array_key_exists($node->tagName, $val_array)) {
            
                            if (!is_array($val_array[$node->tagName]) || $type_array[$node->tagName] == 'hash') {
                                $existing_val = $val_array[$node->tagName];
                                unset($val_array[$node->tagName]);
                                $val_array[$node->tagName][0] = $existing_val;
                                $type_array[$node->tagName] = 'array';
                            }
                            $val_array[$node->tagName][] = $val;
            
                        } else {
            
                            $val_array[$node->tagName] = $val;
                            if (is_array($val)) {
                                $type_array[$node->tagName] = 'hash';
                            }
            
                        } // end if array key exists
            
                    } // end if elment node
                }// end for each
            
                if (count($val_array) == 0) {
                    return $curr_node->nodeValue;
                } else {
                    return $val_array;
                }
            
            } // end function xml to arr
            
            ?>
            

            示例输出

            
            ----
            
            Array
            (
                [PartnerID] => 5550000100-003
                [PartnerType] => PTNR_INTER_CONSIGNEE
                [OperatingUnit] => 100
                [Status] => ACTIVE
                [CustomerSeqNumber] => 111
                [CustomerName] => Greg Co
                [Address1] => 123 Any Ln
                [Address2] => ?
                [Address3] => ?
                [Address4] => ?
                [Address5] => ?
                [City] => Somplace
                [PostalCode] => 60123
                [State] => CA
                [CountryCode] => US
                [TaxReference] => 222
                [PartyRelated] => Y
                [BusinessUnit] => GSBU
                [Region] => GSRGN
                [LocationName] => DBA Mac Head Computing
                [LoadOnly] => N
                [VSTM] => 333
                [MilitaryCustomerFlag] => Y
                [USFederalGovernmentCustomer] => Y
                [Non-USGovernmentCustomer] => Y
                [Vastera:EPCIActivity] => Array
                    (
                        [EPCIActivityNuclearCode] => NUCLEAR
                        [EPCIActivityNuclearValue] => N
                        [EPCIActivityNuclearApproveDate] => 2011-05-16:07:19:37
                        [EPCIActivityNuclearExpireDate] => 2056-12-31:12:00:00
                        [EPCIActivityNuclearCountry] => US
                        [EPCIActivityChemBioCode] => CHEM_BIO
                        [EPCIActivityChemBioValue] => N
                        [EPCIActivityChemBioApproveDate] => 2011-05-16:07:19:37
                        [EPCIActivityChemBioExpireDate] => 2056-12-31:12:00:00
                        [EPCIActivityChemBioCountry] => US
                        [EPCIActivityMissileCode] => MISSILE
                        [EPCIActivityMissileValue] => N
                        [EPCIActivityMissileApproveDate] => 2011-05-16:07:19:37
                        [EPCIActivityMissileExpireDate] => 2056-12-31:12:00:00
                        [EPCIActivityMissileCountry] => US
                    )
            
                [SourceSystem] => GSB2BSS
                [CreatedDate] => 2011-05-16:07:18:55
                [CreatedBy] => c18530
                [LastModifiedDate] => 2011-05-16:07:18:55
                [LastModifiedBy] => c18530
                [ContactName] => Greg, "Da Man" Skluacek
                [ContactTitle] => Head Honcho
                [ContactPhone] => 555-555-5555
                [ContactFax] => 666-666-6666
                [ContactEmail] => gskluzacek@gregco.com
                [ContactWeb] => www.gregco.com
            )
            
            ----
            
            Array
            (
                [orderNumber] => 123
                [customerAddress] => Array
                    (
                        [0] => Array
                            (
                                [type] => Ship To
                                [name] => Bob McFly
                                [addr1] => 123 Lincoln St
                                [city] => Chicago
                                [state] => IL
                                [zip] => 60001
                            )
            
                        [1] => Array
                            (
                                [type] => Bill To
                                [name] => McFly Products Inc.
                                [addr1] => P.O. Box 6695
                                [city] => New York
                                [state] => NY
                                [zip] => 99081-6695
                            )
            
                    )
            
                [item] => Array
                    (
                        [0] => Array
                            (
                                [line] => 1
                                [part] => 123001A
                                [qty] => 5
                                [price] => 10.25
                            )
            
                        [1] => Array
                            (
                                [line] => 2
                                [part] => 456002B
                                [qty] => 3
                                [price] => 20.50
                            )
            
                        [2] => Array
                            (
                                [line] => 3
                                [part] => 789003C
                                [qty] => 1
                                [price] => 41.00
                            )
            
                    )
            
                [orderSubTotal] => 133.25
                [tax] => 6.66
                [shipping] => 10.00
                [orderTotal] => 149.91
            )
            
            --------
            

            【讨论】:

              【解决方案8】:

              嘿@Co​​nrad,我只是修改了您的代码,以便与数字数组一起工作:

              /**
               * Build A XML Data Set
               *
               * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
               * @param string $startElement Root Opening Tag, default fx_request
               * @param string $xml_version XML Version, default 1.0
               * @param string $xml_encoding XML Encoding, default UTF-8
               * @return string XML String containig values
               * @return mixed Boolean false on failure, string XML result on success
               */
              public static function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8'){
                  if(!is_array($data)){
                      $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
                      trigger_error($err);
                      if($this->_debug) echo $err;
                      return false; //return false error occurred
                  }
                  $xml = new XmlWriter();
                  $xml->openMemory();
                  $xml->startDocument($xml_version, $xml_encoding);
                  $xml->startElement($startElement);
              
                  /**
                   * Write XML as per Associative Array
                   * @param object $xml XMLWriter Object
                   * @param array $data Associative Data Array
                   */
                  function write(XMLWriter $xml, $data){
                      foreach($data as $key => $value){
                          if (is_array($value) && isset($value[0])){
                              foreach($value as $itemValue){
                                  //$xml->writeElement($key, $itemValue);
              
                                  if(is_array($itemValue)){
                                      $xml->startElement($key);
                                      write($xml, $itemValue);
                                      $xml->endElement();
                                      continue;
                                  } 
              
                                  if (!is_array($itemValue)){
                                      $xml->writeElement($key, $itemValue."");
                                  }
                              }
                          }else if(is_array($value)){
                              $xml->startElement($key);
                              write($xml, $value);
                              $xml->endElement();
                              continue;
                          } 
              
                          if (!is_array($value)){
                              $xml->writeElement($key, $value."");
                          }
                      }
                  }
                  write($xml, $data);
              
                  $xml->endElement();//write end element
                  //returns the XML results
                  return $xml->outputMemory(true);
              }
              

              所以你可以转换这个:

              $mArray["invitations"]["user"][0]["name"] = "paco";
              $mArray["invitations"]["user"][0]["amigos"][0] = 82;
              $mArray["invitations"]["user"][0]["amigos"][1] = 29;
              $mArray["invitations"]["user"][0]["amigos"][2] = 6;
              
              $mArray["invitations"]["user"][1]["name"] = "jose";
              $mArray["invitations"]["user"][1]["amigos"][0] = 43;
              $mArray["invitations"]["user"][1]["amigos"][1]["tuyos"] = 32;
              $mArray["invitations"]["user"][1]["amigos"][1]["mios"] = 79;
              $mArray["invitations"]["user"][1]["amigos"][2] = 11;
              
              $mArray["invitations"]["user"][2]["name"] = "luis";
              $mArray["invitations"]["user"][2]["amigos"][0] = 65;
              

              进入这个xml:

              <invitations>
              <user>
                  <name>paco</name>
                  <amigos>82</amigos>
                  <amigos>29</amigos>
                  <amigos>6</amigos>
              </user>
              <user>
                  <name>jose</name>
                  <amigos>43</amigos>
                  <amigos>
                      <tuyos>32</tuyos>
                      <mios>79</mios>
                  </amigos>
                  <amigos>11</amigos>
              </user>
              <user>
                  <name>luis</name>
                  <amigos>65</amigos>
              </user>
              

              我希望我能帮助别人解决这个问题

              【讨论】:

                【解决方案9】:

                你见过 PEAR 包 XML_Serializer 吗?

                pear_php_XML_Serializer

                【讨论】:

                  【解决方案10】:

                  我同意这是 PHP 文档已经放弃的一个领域,但对我来说,我总是将 SimpleXML 与 xml2Array 函数之类的东西混合使用。借助 print_r 之类的转储函数,您从 simpleXML 获得的 Xml 并不难导航。

                  【讨论】:

                    【解决方案11】:

                    这建立在 Ángel López 的回答之上。添加了对属性的支持。如果元素有属性,则以@为前缀,并以空字符串为键引用实际元素内容。

                    /**
                     * Build an XML Data Set
                     *
                     * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
                     * @param string $startElement Root Opening Tag, default fx_request
                     * @param string $xml_version XML Version, default 1.0
                     * @param string $xml_encoding XML Encoding, default UTF-8
                     * @return string XML String containig values
                     * @return mixed Boolean false on failure, string XML result on success
                     */
                    function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8'){
                      if(!is_array($data)){
                        $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
                        trigger_error($err);
                        //if($this->_debug) echo $err;
                        return false; //return false error occurred
                      }
                      $xml = new XmlWriter();
                      $xml->openMemory();
                      $xml->startDocument($xml_version, $xml_encoding);
                      $xml->startElement($startElement);
                    
                      /**
                       * Write keys in $data prefixed with @ as XML attributes, if $data is an array. When an @ prefixed key is found, a '' key is expected to indicate the element itself.
                       * @param object $xml XMLWriter Object
                       * @param array $data with attributes filtered out
                       */
                      function writeAttr(XMLWriter $xml, $data) {
                        if(is_array($data)) {
                          $nonAttributes = array();
                          foreach($data as $key => $val) {
                            //handle an attribute with elements
                            if($key[0] == '@') {
                              $xml->writeAttribute(substr($key, 1), $val);
                            } else if($key == '') {
                              if(is_array($val)) $nonAttributes = $val;
                              else $xml->text("$val");
                            }
                    
                            //ignore normal elements
                            else $nonAttributes[$key] = $val;
                          }
                          return $nonAttributes;
                        }
                        else return $data;
                      }
                    
                      /**
                       * Write XML as per Associative Array
                       * @param object $xml XMLWriter Object
                       * @param array $data Associative Data Array
                       */
                      function writeEl(XMLWriter $xml, $data) {
                        foreach($data as $key => $value) {
                          if(is_array($value) && isset($value[0])) { //numeric array
                            foreach($value as $itemValue){
                              if(is_array($itemValue)) {
                                $xml->startElement($key);
                                $itemValue = writeAttr($xml, $itemValue);
                                writeEl($xml, $itemValue);
                                $xml->endElement();
                              } else {
                                $itemValue = writeAttr($xml, $itemValue);
                                $xml->writeElement($key, "$itemValue");
                              }
                            }
                          } else if(is_array($value)) { //associative array
                            $xml->startElement($key);
                            $value = writeAttr($xml, $value);
                            writeEl($xml, $value);
                            $xml->endElement();
                          } else { //scalar
                            $value = writeAttr($xml, $value);
                            $xml->writeElement($key, "$value");
                          }
                        }
                      }
                      writeEl($xml, $data);
                    
                      $xml->endElement();//write end element
                      //returns the XML results
                      return $xml->outputMemory(true);
                    }
                    

                    所以你可以转换这个:

                    $mArray["invitations"]["user"][0]["@name"] = "paco";
                    $mArray["invitations"]["user"][0][""]["amigos"][0] = 82;
                    $mArray["invitations"]["user"][0][""]["amigos"][1] = 29;
                    $mArray["invitations"]["user"][0][""]["amigos"][2] = 6;
                    
                    $mArray["invitations"]["user"][1]["@name"] = "jose";
                    $mArray["invitations"]["user"][1][""]["amigos"][0] = 43;
                    $mArray["invitations"]["user"][1][""]["amigos"][1]["tuyos"] = 32;
                    $mArray["invitations"]["user"][1][""]["amigos"][1]["mios"] = 79;
                    $mArray["invitations"]["user"][1][""]["amigos"][2] = 11;
                    
                    $mArray["invitations"]["user"][2]["@name"] = "luis";
                    $mArray["invitations"]["user"][2][""]["amigos"][0] = 65;
                    

                    进入这个xml:

                    <invitations>
                      <user name="paco">
                        <amigos>82</amigos>
                        <amigos>29</amigos>
                        <amigos>6</amigos>
                      </user>
                      <user name="jose">
                        <amigos>43</amigos>
                        <amigos>
                          <tuyos>32</tuyos>
                          <mios>79</mios>
                        </amigos>
                        <amigos>11</amigos>
                      </user>
                      <user name="luis">
                        <amigos>65</amigos>
                      </user>
                    </invitations>
                    

                    谢谢天使。

                    【讨论】:

                    • 很酷,但如果你像这样制作 assoc 数组,它就不起作用了:array('123' =&gt; 'asdf') 也许你应该检查每个键是否是数字。
                    【解决方案12】:

                    根据这里的答案,我制作了 github repo https://github.com/jmarceli/array2xml

                    也许不是互联网上最漂亮的 repo,但代码似乎运行良好。

                    这里是可以使用的代码:

                    // Based on: http://stackoverflow.com/questions/99350/passing-php-associative-arrays-to-and-from-xml
                    class ArrayToXML {
                      private $version;
                      private $encoding;
                      /*
                       * Construct ArrayToXML object with selected version and encoding 
                       *
                       * for available values check XmlWriter docs http://www.php.net/manual/en/function.xmlwriter-start-document.php
                       * @param string $xml_version XML Version, default 1.0
                       * @param string $xml_encoding XML Encoding, default UTF-8
                       */
                      public function __construct($xmlVersion = '1.0', $xmlEncoding = 'UTF-8') {
                        $this->version = $xmlVersion;
                        $this->encoding = $xmlEncoding;
                      }
                      /**
                       * Build an XML Data Set
                       *
                       * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
                       * @param string $startElement Root Opening Tag, default data
                       * @return string XML String containig values
                       * @return mixed Boolean false on failure, string XML result on success
                       */
                      public function buildXML($data, $startElement = 'data'){
                        if(!is_array($data)){
                          $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
                          trigger_error($err);
                          //if($this->_debug) echo $err;
                          return false; //return false error occurred
                        }
                        $xml = new XmlWriter();
                        $xml->openMemory();
                        $xml->startDocument($this->version, $this->encoding);
                        $xml->startElement($startElement);
                        $this->writeEl($xml, $data);
                        $xml->endElement();//write end element
                        //returns the XML results
                        return $xml->outputMemory(true);
                      }
                      /**
                       * Write keys in $data prefixed with @ as XML attributes, if $data is an array. 
                       * When an @ prefixed key is found, a '%' key is expected to indicate the element itself, 
                       * and '#' prefixed key indicates CDATA content
                       *
                       * @param object $xml XMLWriter Object
                       * @param array $data with attributes filtered out
                       */
                      protected function writeAttr(XMLWriter $xml, $data) {
                        if(is_array($data)) {
                          $nonAttributes = array();
                          foreach($data as $key => $val) {
                            //handle an attribute with elements
                            if($key[0] == '@') {
                              $xml->writeAttribute(substr($key, 1), $val);
                            } else if($key[0] == '%') {
                              if(is_array($val)) $nonAttributes = $val;
                              else $xml->text($val);
                            } elseif($key[0] == '#') {
                              if(is_array($val)) $nonAttributes = $val;
                              else {
                                $xml->startElement(substr($key, 1));
                                $xml->writeCData($val);
                                $xml->endElement();
                              }
                            }
                            //ignore normal elements
                            else $nonAttributes[$key] = $val;
                          }
                          return $nonAttributes;
                        }
                        else return $data;
                      }
                      /**
                       * Write XML as per Associative Array
                       *
                       * @param object $xml XMLWriter Object
                       * @param array $data Associative Data Array
                       */
                      protected function writeEl(XMLWriter $xml, $data) {
                        foreach($data as $key => $value) {
                          if(is_array($value) && !$this->isAssoc($value)) { //numeric array
                            foreach($value as $itemValue){
                              if(is_array($itemValue)) {
                                $xml->startElement($key);
                                $itemValue = $this->writeAttr($xml, $itemValue);
                                $this->writeEl($xml, $itemValue);
                                $xml->endElement();
                              } else {
                                $itemValue = $this->writeAttr($xml, $itemValue);
                                $xml->writeElement($key, "$itemValue");
                              }
                            }
                          } else if(is_array($value)) { //associative array
                            $xml->startElement($key);
                            $value = $this->writeAttr($xml, $value);
                            $this->writeEl($xml, $value);
                            $xml->endElement();
                          } else { //scalar
                            $value = $this->writeAttr($xml, $value);
                            $xml->writeElement($key, "$value");
                          }
                        }
                      }
                      /*
                       * Check if array is associative with string based keys
                       * FROM: http://stackoverflow.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential/4254008#4254008
                       *
                       * @param array $array Array to check
                       */
                      protected function isAssoc($array) {
                        return (bool)count(array_filter(array_keys($array), 'is_string'));
                      }
                    }
                    

                    之后,只需使用 ArrayToXML 类。示例:

                    $xml = new ArrayToXML();
                    print $xml->buildXML($input);
                    

                    【讨论】:

                      【解决方案13】:

                      下面的类使用simplexml实现相同,只需要遍历数组并调用ximplexml的addchild即可。

                      http://snipplr.com/view.php?codeview&id=3491

                      【讨论】:

                        【解决方案14】:

                        从xml字符串中获取assoc数组的最简单方法:

                        <?
                        $data_array = (array) simplexml_load_string($xml_string);
                        ?>
                        

                        【讨论】:

                          【解决方案15】:
                          /**
                           * Write XML as per Associative Array
                           * @param object $xml XMLWriter Object
                           * @param array $data Associative Data Array
                           */
                          function writeXmlRecursive(XMLWriter $xml, $data){
                              foreach($data as $key => $value){
                                  if (is_array($value) && isset($value[0])){
                                      $xml->startElement($key);
                                      foreach($value as $itemValue){
                          
                                          if(is_array($itemValue)){
                                              writeXmlRecursive($xml, $itemValue);
                                          }
                                          else
                                          {
                                              $xml->writeElement($key, $itemValue."");
                                          }
                                      }
                                      $xml->endElement();
                          
                                  }else if(is_array($value)){
                                      $xml->startElement($key);
                                      writeXmlRecursive($xml, $value);
                                      $xml->endElement();
                                      continue;
                                  }
                          
                                  if (!is_array($value)){
                                      $xml->writeElement($key, $value."");
                                  }
                              }
                          }
                          

                          这是最终版本,它可以从具有 4 个嵌套级别的数组中提供我想要的 ahat

                          <items>
                          <item>
                            <id_site>59332</id_site>
                            <id>33</id>
                            <code>196429985</code>
                            <tombid>23</tombid>
                            <tombcode>196429985</tombcode>
                            <religion></religion>
                            <lastname>lastname</lastname>
                            <firstname>name</firstname>
                            <patronymicname>patronymicname</patronymicname>
                            <sex>1</sex>
                            <birthday>2</birthday>
                            <birthmonth>4</birthmonth>
                            <birthyear>1946</birthyear>
                            <deathday>13</deathday>
                            <deathmonth>5</deathmonth>
                            <deathyear>2006</deathyear>
                            <s_comments></s_comments>
                            <graveyard>17446</graveyard>
                            <latitude></latitude>
                            <longitude></longitude>
                            <images>
                             <image>
                              <siteId>52225</siteId>
                              <fileId>62</fileId>
                              <prefix>0</prefix>
                              <path>path</path>
                             </image>
                             <image>
                              <siteId>52226</siteId>
                              <fileId>63</fileId>
                              <prefix>0</prefix>
                              <path>path</path>
                             </image>
                            </images>
                           </item>
                          <items>
                          

                          【讨论】:

                            猜你喜欢
                            • 2012-06-14
                            • 1970-01-01
                            • 1970-01-01
                            • 2017-12-14
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-03-21
                            • 1970-01-01
                            • 2012-09-12
                            相关资源
                            最近更新 更多