2008-09-19 9 views
16

Existe-t-il un moyen facile de rassembler un tableau associatif PHP vers et à partir de XML? Par exemple, je le tableau suivant:Passage de tableaux associatifs PHP vers et à partir de XML

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

Comment pourrais-je transformer en quelque chose de similaire au XML suivant que quelques lignes que possible, puis de nouveau?

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

Je ne me soucie pas vraiment si je dois changer la structure du tableau un peu ou si le code XML qui sort est différent de l'exemple ci-dessus. J'ai essayé de travailler avec PHP et de XMLReaderXMLWriter, mais la documentation est si pauvre et le code que j'ai produit en conséquence ne ressemble en rien à ce que je pense qu'il devrait ressembler à:

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

-t-il vraiment doit être plus difficile que cela pour obtenir un vidage XML brut de base d'un tableau PHP sans écrire ma propre classe personnalisée?

J'essaie d'éviter PEAR. En plus des problèmes de configuration que j'ai rencontrés, je ne suis jamais resté avec l'un des paquets que j'ai utilisé.

Répondre

6

Pour ceux d'entre vous de ne pas utiliser les packages PEAR, mais vous avez installé PHP5. Cela a fonctionné pour moi:

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

si vous avez des tableaux non associatifs (ou plutôt, des tableaux contenant des nombres) dans vos données, en ajoutant un 'if (is_numeric ($ key)) $ key = "item";' au début du bloc foreach (avant is_array) fait l'affaire. – Kemal

+1

Pour être fonctionnel avec les tableaux numériques, ajoutez '$ fKey = is_numeric ($ key)? 'numericValue': $ key; ** avant ** 'if (is_array ($ value))', et utilisez '$ fKey' dans le reste de l'instruction foreach. – Vassilis

+1

Oh @VassilisGr, j'ai fait quelque chose comme ça: 'if (is_numeric ($ key)) {$ key = 'node'; } 'et déplacé la fonction' write' en dehors, vous ne pouvez pas déclarer deux fois la même fonction, mais @Conrad va maintenant le faire. (Merde, j'ai vu maintenant @disq commenter haha) – Wiliam

2

Essayez Zend_Config et Zend Framework en général.

J'imagine que ce serait un processus en deux étapes: array vers Zend_Config, Zend_Config vers XML.

2

Cela ressemble à un travail pour SimpleXML.

Je suggère une structure XML légèrement différente ..

et je me demande pourquoi vous avez besoin de convertir d'un tableau -> XML et retour .. Si vous pouvez modifier la structure du tableau que vous avez dit pourquoi ne pas simplement générer XML au lieu? Si un morceau de code existe déjà qui prend cette configuration de tableau, modifiez-le simplement pour accepter le XML à la place. Ensuite, vous avez 1 format de données/type d'entrée, et ne pas besoin de convertir tout ..

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

Je suis d'accord c'est un domaine que la documentation de PHP a laissé tomber la balle, mais pour moi je l'ai toujours utilisé le SimpleXML mélangé avec quelque chose comme les fonctions xml2Array. Le XML que vous obtenez de simpleXML n'est pas si difficile à naviguer avec l'aide d'une fonction de vidage comme print_r.

3

J'ai eu quelques-uns de ces mêmes questions, et je crée deux classes:

BXML

Une classe qui étend SimpleXML et corrige certains des problèmes qu'elle a. Comme ne pas être en mesure d'ajouter des noeuds CData ou des noeuds Comment. J'ai également ajouté quelques fonctionnalités supplémentaires, comme l'utilisation de la fonctionnalité de flux php pour ajouter des nœuds enfants $oXml->AddChild("file:///user/data.xml") ou ajouter des nœuds enfants de chaînes XML comme $oXml->AddChild("<more><xml>yes</xml></more>"); mais je voulais simplement corriger les problèmes simplesXML.

Barray

J'ai étendu la classe ArrayObject de sorte que toutes les fonctionnalités de tableau pourrait être orienté objet et cohérente, de sorte que vous n'avez pas besoin de se rappeler que array_walk fonctionne sur le tableau par référence, alors que array_filter fonctionne sur la tableau par valeur. Donc, vous pouvez faire des choses comme $oArray->flip()->Reverse()->Walk(/*callback*/); puis toujours accéder à la valeur de la même manière que vous le souhaitez normalement $oArray[key].

Les deux méthodes sont éditées en tant que tableaux et Xml, ce qui vous permet de passer d'une application à l'autre. Donc, vous pouvez $oXml->AsArray(); ou $oArray->AsXml(); J'ai trouvé qu'il était plus facile de faire cela que de passer constamment des choses entre les méthodes array2xml ou xml2array.

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

Les deux classes sont surchargées peuvent être pour faire une classe personnalisée de votre choix et peuvent être utilisés indépendamment les uns des autres.

+0

L'extension de SimpleXML pour faire cela est une bonne idée! – thomasrutter

2

Voici une fonction que j'ai écrite pour prendre XML et le convertir en un tableau associatif PHP. Une mise en garde est que l'identifiant ne gère pas actuellement les attributs ou les données c. Bien qu'il traite les balises XML répétées au même niveau en les plaçant dans un tableau nommé d'après le 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>[email protected]</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 

?> 

exemple sortie


---- 

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] => 6
    [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] => [email protected] 
    [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 
) 

-------- 
2

Hey @Conrad je modifie simplement votre code pour bien travailler avec des tableaux numériques:

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

si yo peut convertir ceci:

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

dans ce fichier:

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

J'espère que je peux aider quelqu'un avec ce

+0

Je suis modifier votre code et l'afficher comme réponse –

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

La façon la plus simple d'obtenir tableau assoc de chaîne xml:

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

Ce construit sur Ángel López de répondre. Ajout du support pour les attributs. Si un élément a des attributs, préfixez-les avec @, et reportez-vous au contenu de l'élément réel avec une chaîne vide comme clé.

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

si yo peut convertir ceci:

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

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

Merci Ángel.

+0

Cool mais ne fonctionne pas si vous faites un tableau assoc comme ceci: 'array ('123' => 'asdf')' Probablement vous devriez vérifier chaque clé pour être un nombre. – jmarceli

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

Ceci est la version finale, qui donnent ahat je veux du tableau avec 4 niveau imbriqué

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

Sur la base des réponses ici, je fait repo github https://github.com/jmarceli/array2xml

Peut-être pas la plus jolie prise en pension sur la Internet mais le code semble bien fonctionner.

Voici le code qui peut être utilisé:

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

Ensuite, utilisez la classe ArrayToXML. Exemple:

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