Vários dias atrás, tentei analisar um arquivo XML em uma matriz associativa. Com o uso de implexml_load_file
ou simplexml_load_string
, combinado com json_decode
e json_encode
parece funcionar perfeitamente.
Dê uma olhada na seguinte função:
/**
* @param SimpleXMLElement $xml
* @return mixed
*/
function toAssocArray($xml) {
$string = json_encode($xml);
$array = json_decode($string, true);
return $array;
}
Embora pareça bastante útil, há uma limitação em relação ao <! CDATA […]> .
Considere o seguinte xml:
<?xml version="1.0" encoding="utf-8"?>
<sample>
<sample1>foo<!CDATA[bar]></sample1>
<sample2><!CDATA[foobar]></sample2>
</sample>
Se usarmos toAssocArray
, o valor de sample1 será “foobar”, como esperado. Mas se dermos uma olhada no valor de sample2 , notaremos que ele contém um array vazio – o conteúdo real “foobar” é perdido.
Para nos livrarmos desse comportamento, temos que remover o <! CDATA [..]> e filtrar seu valor (porque normalmente você armazena dados que poderiam ser interpretados como XML / HTML, mas não deveriam).
Portanto, temos que usar preg_replace_callback
na string XML junto com uma função de filtro personalizada, antes de analisá-la em um SimpleXMLElement e, finalmente, em um array associativo.
Isso tem uma desvantagem: se quisermos obter o XML de um arquivo, temos que usar em file_get_contents
vez de simplexml_load_file
, porque simplexml_load_file
retornará um SimpleXMLElement, no qual não podemos aplicar nosso filtro.
Portanto, estas são nossas funções finais:
/**
* @param SimpleXMLElement $xml
* @return mixed
*/
function toAssocArray($xml) {
$string = json_encode($xml);
$array = json_decode($string, true);
return $array;
}
/**
* @param string $xml
* @return SimpleXMLElement
*/
function betterxml_load_string($xml) {
$string = preg_replace_callback('/<![CDATA[(.*)]]>/', 'cdata_filter', $xml);
$xml = simplexml_load_string($string);
return $xml;
}
/**
* @param array $matches
* @return string
*/
function cdata_filter($matches) {
$converted = htmlspecialchars($matches[1];
$trimmed = trim($converted);
return $trimmed;
}
E nós o usamos da seguinte maneira:
$xml = file_get_contents('some/xml/file.xml');
$assoc = toAssocArray($xml);
echo $assoc['sample1'];