Domanda

Esiste un modo semplice per eseguire il marshalling di un array associativo PHP da e verso XML?Ad esempio, ho il seguente array:

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

Come potrei trasformarlo in qualcosa di simile al seguente XML nel minor numero di righe possibile, e poi viceversa?

<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>

Non mi interessa davvero se devo cambiare un po' la struttura dell'array o se l'XML che ne esce è diverso dall'esempio sopra.Ho provato a lavorare con PHP XMLReader E XMLWriter, ma la documentazione è così scarsa e il codice che ho prodotto di conseguenza non assomiglia per niente a quello che penso dovrebbe essere:

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

Deve davvero essere più difficile di così ottenere un dump XML semplice e grezzo di un array PHP senza scrivere la mia classe personalizzata?

Cerco di evitare PEAR.Oltre ai problemi di configurazione che ho avuto con esso, non sono mai rimasto bloccato con nessuno dei pacchetti che ho utilizzato.

È stato utile?

Soluzione

Per quelli di voi che non utilizzano i pacchetti PEAR, ma hanno PHP5 installato.Questo ha funzionato per me:

/**
 * 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); 
}

Altri suggerimenti

SimpleXML funziona benissimo per il tuo uso.

Ho avuto alcuni di questi stessi problemi e quindi ho creato due classi:

bXml

Una classe che estende SimpleXml e corregge alcuni dei problemi che presenta.Come non essere in grado di aggiungere nodi CData o nodi Commento.Ho anche aggiunto alcune funzionalità aggiuntive, come l'utilizzo della funzionalità dei flussi php per aggiungere nodi figlio $oXml->AddChild("file:///user/data.xml") o aggiungere nodi figlio di stringhe XML come $oXml->AddChild("<more><xml>yes</xml></more>"); ma fondamentalmente volevo solo risolvere i semplici problemi XML.

bArray

Ho esteso la classe ArrayObject in modo che tutte le funzionalità dell'array possano essere orientate agli oggetti e coerenti, quindi non è necessario ricordare che array_walk opera sull'array per riferimento, mentre array_filter opera sull'array per valore.Quindi puoi fare cose del tipo $oArray->flip()->Reverse()->Walk(/*callback*/); quindi accedi comunque al valore nello stesso modo in cui lo faresti normalmente $oArray[key].

Entrambi i metodi vengono visualizzati come Array e Xml in modo da poter passare facilmente dall'uno all'altro.Così puoi $oXml->AsArray(); O $oArray->AsXml(); Ho scoperto che era più semplice farlo piuttosto che passare costantemente le cose avanti e indietro tra i metodi array2xml o xml2array.

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

Entrambe le classi possono essere sovrascritte per creare una classe personalizzata di tua scelta e possono essere utilizzate indipendentemente l'una dall'altra.

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);

Prova Zend_Config e Zend Framework in generale.

Immagino che sarebbe un processo in 2 fasi:array in Zend_Config, Zend_Config in XML.

Sembra un lavoro per SimpleXML.

Suggerirei una struttura XML leggermente diversa..

E chiediti perché devi convertire da un array -> XML e viceversa..Se puoi modificare la struttura dell'array come hai detto, perché non generare semplicemente XML?Se esiste già una parte di codice che accetta quella configurazione di array, è sufficiente modificarla per accettare invece l'XML.Quindi hai 1 formato dati/tipo di input e non è necessario convertirli affatto.

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

Ecco una funzione che ho scritto per prendere XML e convertirlo in un array associativo PHP.Un avvertimento è che id attualmente non gestisce attributi o c-data.Sebbene gestirà i tag XML ripetuti allo stesso livello inserendoli in un array che prende il nome dal tag.


<?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

?>

uscita di esempio


----

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
)

--------

Ehi @Conrad, ho appena modificato il tuo codice per funzionare bene con gli array numerici:

/**
 * 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);
}

quindi puoi convertire questo:

$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;

in questo 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>

Spero di poter aiutare qualcuno con questo

Hai visto il pacchetto PEAR XML_Serializer?

Pear_php_XML_Serializer

Sono d'accordo che questa è un'area in cui la documentazione di PHP ha lasciato cadere la palla, ma per me ho sempre usato SimpleXML mescolato con qualcosa come le funzioni xml2Array.L'Xml che ottieni da simpleXML non è così difficile da navigare con l'aiuto di una funzione di dumping come print_r.

Ciò si basa sulla risposta di Ángel López.Aggiunto supporto per gli attributi.Se un elemento ha attributi, anteponili con @ e fai riferimento al contenuto effettivo dell'elemento con una stringa vuota come chiave.

/**
 * 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);
}

quindi puoi convertire questo:

$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;

in questo 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>

Grazie Angelo.

Sulla base delle risposte qui ho creato il repository Github https://github.com/jmarceli/array2xml

Forse non è il repository più carino su Internet, ma il codice sembra funzionare bene.

Ecco il codice che può essere utilizzato:

// 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'));
  }
}

Dopodiché basta usare il file ArrayToXML classe.Esempio:

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

La classe seguente utilizza simplexml per ottenere lo stesso risultato, è sufficiente scorrere l'array e chiamare addchild di ximplexml.

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

Il modo più semplice per ottenere l'array assoc dalla stringa xml:

<?
$data_array = (array) simplexml_load_string($xml_string);
?>
/**
 * 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."");
        }
    }
}

Questa è la versione finale, che dà quello che voglio dall'array con 4 livelli nidificati

<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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top