2008-09-19 13 views
16

¿Existe alguna forma fácil de ordenar una matriz asociativa PHP desde y hacia XML? Por ejemplo, tengo la siguiente matriz:Pasar matrices asociativas de PHP hacia y desde XML

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

¿cómo iba a convertirlo en algo similar a la siguiente XML en tan pocas líneas como sea posible, luego de vuelta otra vez?

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

Realmente no me importa si tengo que cambiar la estructura de matriz un poco o si el código XML que sale es diferente al ejemplo anterior. He estado tratando de trabajar con PHP de XMLReader y XMLWriter, pero la documentación es tan pobre y el código que he producido como consecuencia parece en nada a lo que siento que debe ser similar:

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

es lo que realmente tiene que ser más difícil que eso para obtener un volcado XML básico sin formato de una matriz PHP sin escribir mi propia clase personalizada?

Intento evitar PEAR. Además de los dolores de cabeza que he tenido con la configuración, nunca me he quedado con ninguno de los paquetes que he usado.

Respuesta

6

Para aquellos que no estén usando los paquetes de PEAR, pero tienes instalado PHP5. Esto funcionó para mí:

/** 
* 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 tiene matrices no asociativas (o más bien, claves de matriz con números en ellas) en sus datos, agregando un 'if (is_numeric ($ key)) $ key = "item";' al comienzo del bloque foreach (antes de is_array) funciona el truco. – Kemal

+1

Para ser funcional con arreglos numéricos también, agregue '$ fKey = is_numeric ($ key)? 'numericValue': $ key; '** before **' if (is_array ($ value)) 'statement, y use' $ fKey' en el resto de la instrucción foreach. – Vassilis

+1

Oh @VassilisGr, hice algo así allí: 'if (is_numeric ($ key)) {$ key = 'node'; } 'y movió' function write' afuera, no puede declarar dos veces la misma función, pero @Conrad ahora lo hará. (Mierda, ahora vi @disq comment jaja) – Wiliam

2

Pruebe Zend_Config y Zend Framework en general.

Imagino que sería un proceso de 2 pasos: una matriz para Zend_Config, Zend_Config para XML.

2

Suena como un trabajo para SimpleXML.

que sugeriría una estructura XML ligeramente diferente ..

Y preguntarse por qué es necesario convertir de una matriz -> XML y volver .. Si se puede modificar la estructura de matriz como se ha dicho por qué no sólo generar XML ¿en lugar? Si ya existe algún fragmento de código que tome esa configuración de matriz, simplemente modifíquela para aceptar el XML en su lugar. Entonces usted tiene 1 tipo de formato de datos/entrada, y no es necesario para convertir a todos ..

<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

estoy de acuerdo esta es un área que la documentación de PHP ha dejado caer la pelota, pero para mí siempre he utilizado el SimpleXML mezclado con algo así como las funciones xml2Array. El Xml que obtienes de simpleXML no es tan difícil de navegar con la ayuda de una función de dumping como print_r.

3

que he tenido algunos de estos mismos problemas, y por lo que he creado dos clases:

bXml

una clase que se extiende SimpleXML y corrige algunos de los problemas que tiene. Como no poder agregar nodos CData o nodos Comment. También agregué algunas características adicionales, como usar la funcionalidad de las corrientes de php para agregar nodos secundarios $oXml->AddChild("file:///user/data.xml") o agregar los nodos hijos de cadenas XML como $oXml->AddChild("<more><xml>yes</xml></more>");, pero básicamente solo quería solucionar los problemas simples de XML.

Barray

extendí la clase ArrayObject de manera que toda la funcionalidad de gama podría ser orientado a objetos y consistente, por lo que no es necesario recordar que array_walk opera en la matriz por referencia, mientras que array_filter opera en el array por valor Por lo tanto, puede hacer cosas como $oArray->flip()->Reverse()->Walk(/*callback*/); y seguir accediendo al valor de la misma manera que normalmente le gustaría $oArray[key].

Ambos métodos se muestran como Arrays y Xml para que pueda saltar sin problemas entre ellos. Entonces puede $oXml->AsArray(); o $oArray->AsXml();. Descubrí que era más fácil hacer esto que pasar constantemente cosas entre los métodos array2xml o xml2array.

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

Ambas clases se pueden anularse para hacer una clase personalizada de su elección y se pueden utilizar de forma independiente el uno del otro.

+0

¡Extender SimpleXML para hacer eso es una idea bastante clara! – thomasrutter

2

Aquí hay una función que escribí para tomar XML y convertirla en una Matriz Asociativa de PHP. Una advertencia es que id no maneja actualmente atributos o datos c. Aunque manejará la etiqueta XML repetida en el mismo nivel al colocarlos en una matriz con el nombre de la etiqueta.


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

?> 

ejemplo de salida


---- 

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 acabo de modificar el código para trabajar bien con matrices numéricas:

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

manera yo puede convertir esto:

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

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

espero poder ayudar a alguien con este

+0

Estoy modificando tu código y lo publico como respuesta –

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 forma más sencilla de obtener matriz asociativa de la cadena XML:

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

Esto se basa en Ángel López de responder. Se agregó soporte para los atributos. Si un elemento tiene atributos, fíjelos con @, y refiérase al contenido real del elemento con una cadena vacía como la clave.

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

manera yo puede convertir esto:

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

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

Gracias Ángel.

+0

Genial pero no funciona si haces una matriz assoc como esta: 'array ('123' => 'asdf')' Probablemente deberías verificar cada tecla por ser un número. – 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.""); 
     } 
    } 
} 

Esta es la versión final, que dan ahat que quiero de matriz con 4 nivel anidado

<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

Sobre la base de las respuestas Aquí hice github repo https://github.com/jmarceli/array2xml

Quizás no sea la cesión temporal más bonitos de la Internet, pero el código parece estar funcionando bien.

Este es el código que puede ser utilizado:

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

Después de eso sólo tiene que utilizar la clase ArrayToXML. Ejemplo:

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