texto - replace in array php
Pasar matrices asociativas PHP hacia y desde XML (15)
¿Existe una forma fácil de ordenar una matriz asociativa PHP desde y hacia XML? Por ejemplo, tengo la siguiente matriz:
$items = array("1", "2",
array(
"item3.1" => "3.1",
"item3.2" => "3.2"
"isawesome" => true
)
);
¿Cómo podría convertirlo en algo similar al siguiente XML en la menor cantidad de líneas posible, y luego de vuelta?
<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 la matriz un poco o si el XML que sale es diferente al ejemplo anterior. He intentado trabajar con XMLReader y XMLWriter de PHP , pero la documentación es muy pobre y el código que he producido como consecuencia no se parece en nada a lo que creo que debería ser:
$xml = SomeXMLWriter::writeArrayToXml($items);
$array = SomeXMLWriter::writeXmlToArray($xml);
¿Realmente tiene que ser más difícil que obtener un volcado de XML básico sin formato de una matriz de 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.
Estoy de acuerdo en que esta es un área en la que la documentación de PHP ha dejado caer la pelota, pero para mí siempre he usado 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.
Prueba Zend_Config y Zend Framework en general.
Me imagino que sería un proceso de 2 pasos: array a Zend_Config, Zend_Config a XML.
Suena como un trabajo para SimpleXML.
Sugeriría una estructura XML ligeramente diferente ...
Y me pregunto por qué necesitas convertir de una matriz -> XML y viceversa. Si puedes modificar la estructura de la matriz como dijiste, ¿por qué no solo generar XML en su 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 tienes 1 formato de datos / tipo de entrada, y no necesitas convertir nada ...
<items>
<item id="1"/>
<item id="2"/>
<item id="3">
<subitems>
<item id="3.1"/>
<item id="3.2" isawesome="true"/>
</subitems>
</item>
</items>
SimpleXML funciona muy bien para su uso.
He tenido algunos de estos problemas, así que creé dos clases:
bXml
Una clase que 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 para que todas las funciones de la matriz pudieran ser orientadas a objetos y consistentes, por lo que no es necesario recordar que array_walk opera en la matriz por referencia, mientras que array_filter opera en la matriz por valor. Entonces puede hacer cosas como $oArray->flip()->Reverse()->Walk(/*callback*/);
luego siga 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 puedes $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 anular para crear una clase personalizada de su elección y se pueden usar independientemente una de la otra.
La siguiente clase usa simplexml para lograr lo mismo, solo necesita recorrer la matriz y llamar a addchild de ximplexml.
Aquí hay una función que escribí para tomar XML y convertirlo 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] => 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] => [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
)
--------
Hola, @Conrad, simplemente modifico tu código para que funcione 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);
}
para que puedas 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 esto
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);
La forma más simple de obtener una matriz assoc de una cadena xml:
<?
$data_array = (array) simplexml_load_string($xml_string);
?>
¿Has visto el paquete PEAR XML_Serializer?
Esto se basa en la respuesta de Ángel López. 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);
}
para que puedas 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 Angel.
/**
* 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 da lo que quiero de una matriz con 4 niveles anidados
<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>
Para aquellos de ustedes que no usan los paquetes PEAR, pero tienen PHP5 instalado. 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);
}
Basado en las respuestas aquí hice github repo https://github.com/jmarceli/array2xml
Tal vez no sea el repositorio más bonito en Internet, pero el código parece estar funcionando bien.
Aquí está el código que puede usarse:
// Based on: http://.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://.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 solo usa la clase ArrayToXML
. Ejemplo:
$xml = new ArrayToXML();
print $xml->buildXML($input);