Como de costumbre, comencemos por ponernos de acuerdo en las definiciones.
Qué es XML
Las siglas XML remiten a eXtensible Markup Language (Lenguaje de etiquetas extendible).
Se trata de texto estructurado mediante etiquetas (Palabras encerradas entre < y >):
<utensilios> <tenedor/> <cuchillo/> </utensilios>
Para qué sirve XML
XML se inventó como un medio de intercambio de información entre sistemas a través de Internet. Al ser un formato basado en texto, era fácil aprovechar la infraestructura existente para comunicarse a través de HTTP.
Hoy en día, XML es utilizado en muchas implementaciones de WebServices (Por ejemplo, las facturas electrónicas) y también para almacenar configuraciones (En el caso del lenguaje Java es muy común encontrar este tipo de archivos, en PHP no tanto).
Cómo se procesa XML usando PHP
Al tratarse de texto, un modo de procesar XML es, como cualquier otro texto… pueden usarse expresiones regulares u otro medio de análisis de texto para interpretar y/o generar las etiquetas.
Claro que no es muy divertido que digamos…
Para comprender completamente lo que viene a continuación se requieren conocimientos de Programación Orientada a Objetos con PHP. Si aún no lo tenés muy claro este curso te puede ayudar.
Otro modo bastante más práctico es usar la biblioteca SimpleXML que viene con PHP.
La clase principal de la biblioteca es SimpleXMLElement
. Con esta clase se puede crear una estructura en memoria a partir de un texto XML y luego recorrerlo en forma sencilla.
Ejemplo de lectura de XML con SimpleXMLElement
El constructor de SimpleXMLElement recibe un texto XML:
<?php $xml = new SimpleXMLElement( '<utensilios><tenedor/><cuchillo/></utensilios>' );
Y a partir de ahí pueden realizarse diversas operaciones para recorrer los elementos.
Una de ellas es buscar elementos explícitamente a través de su XPATH:
$elementos = $xml->xpath('/utensilios/tenedor');
Esta llamada dejará en el array $elementos
todos los nodos tenedor
que se encuentren bajo la clave utensilios
(En este caso es sólo uno, pero eso SimpleXMLElement no lo sabe a priori).
Si agregamos un print_r( $elementos )
veremos :
Array ( [0] => SimpleXMLElement Object ( ) )
Es decir, un array con un único elemento… de tipo SimpleXMLElement, al que podemos nuevamente aplicarle todas las funciones que provee la clase.
Ejemplo de recorrida de XML con SimpleXML
Otra forma de recorrer el texto XML es a través del método children
:
<?php $xml = new SimpleXMLElement( '<utensilios><tenedor/><cuchillo/></utensilios>' ); foreach ( $xml->children() as $child ) { print_r( $child ); }
Esta es la que deberías usar si no conoces exactamente la estructura del XML o si efectivamente tenés que recorrer el archivo completo.
Cómo leer un archivo XML usando PHP
Bueno, con lo que viste hasta ahora el paso que queda es realmente corto… se podría leer el contenido del archivo a una variable y pasarla al constructor de SimpleXMLElement:
<?php $texto = file( 'archivo.xml' ); $xml = new SimpleXMLElement( $texto ); $elementos = $xml->xpath('/utensilios/tenedor'); print_r( $elementos );
O bien pasar directamente la ruta al archivo al constructor:
<?php $xml = new SimpleXMLElement( 'archivo.xml' ); $elementos = $xml->xpath('/utensilios/tenedor'); print_r( $elementos );
Y dejar que SimpleXML se encargue de interpretar si se trata de uno u otro.
Conclusión
Si todavía no te convencí de usar SimpleXML en lugar de hacer las cosas a mano, te invito a leer un poco más sobre el formato XML (Especialmente el manejo de namespaces).
Ahora, si tenés que interactuar con un sistema que está implementado usando XML, bueno… no hay muchas opciones.
Si, por el contrario, estás pensando en usar algún formato de texto para guardar configuración o incluso para intercambiar con otros sistemas, te sugiero darle una mirada a JSON o a YAML
- Cómo enviarencabezados SOAP desde PHP - 09/12/2024
- Por qué PHP 8 no satisface el requisito ^7.3 de composer - 09/12/2024
- Cómo usar PHPUnit - 03/12/2024
Estimado don Mauro: Le comento que tengo unos xml de respuesta que vienen de un Soap, pero a mi criterio son muy complejos para leerlos y me gustaria que me diera un consejo de como extraer algunos campos de estos xml.
Le detallo una de las respuestas
de este xml debo extraer
Job JobName y
ContextId
Agradezco su ayuda
Hola! Lo mejor para trabajar con Soap usando PHP es la librería propia: https://www.php.net/manual/es/book.soap.php, en particular para tu caso el SoapClient (https://www.php.net/manual/es/class.soapclient.php).
Si te interesa profundizar en este tema el curso de WebServices con PHP te puede ayudar: https://www.udemy.com/course/webservices-con-php-desde-cero/?referralCode=8CB81755B995A37C85A5
muchas gracias, me sirvio de mucho, un cliente nos envia la informacion usando soap y a cada rato me quedaba sin memoria. aun asi me gusta mas json
Y sí… la verdad es que SOAP no es precisamente la imagen de la eficiencia, ja.
Es sólo que en ocasiones json (O RESTful en realidad) se queda algo corto por la complejidad de la información a intercambiar.
¿Cómo resolviste el problema de la falta de memoria?
perdon no te dije gracias.
creo un array multidimencional asociativo a partir de un xml
cuando llega a una linea de detalle me crea indices repetidos y me da el siguiente error
Notice: Undefined index: NumeroLinea
Hola Eduardo:
Gracias por tu consulta. Para poder orientarte necesitaría ver el código. ¿Podrías publicarlo?
Saludos!
Hola Mauro !
Primero felicitarte por el aporte que realizas a través de tu sitio y canales, el cual sigo desde hace ya un tiempo.
Acudo a tu persona, y apelando a tu experiencia y basto conocimiento de PHP :), luego de que llevo unos días intentando «leer» la respuesta de un WS SOAP, específicamente la respuesta del método «Login». Al principio tuve problemas para «conectar», me fue imposible realizarlo con la clase SoapClient, por lo lo tuve que hacer con cURL.
Ahora que ya obtengo la respuesta, recibo los datos en un XML con la siguiente estructura:
VentaServicio/VentaServicio/LoginResponse
cliente
empresa
id_sesion
id_usuario
token_encriptado
La verdad, e probado de todas las maneras y formas posible de acceder y obtener el VALOR del «Token» para luego utilizarlo en el resto de los métodos, pero ninguna me a sido posible. Lo más extraño, es que aplicando las mismas técnicas a otras «respuestas» SOAP de ejemplo encontradas, y de mayor complejidad, sí puedo leer sus valores sin problemas. Lamentablemente, no he encontrado ninguna «respuesta» con similar estructura que muestre su correcta manera de recorrerla o de lectura. Sumado a que el «namespace» de LoginResponse me reclama que no tiene una ruta «absoluta» (cosa que solucioné, temporalmente, añadiendo el http://).
$oXML = simplexml_load_string($sXML);
// Now we will register namespace.
$oXML->registerXPathNamespace(‘res’, ‘http://www.w3.org/2003/05/soap-envelope’);
print_r($oXML->registerXPathNamespace(‘res’, ‘http://www.w3.org/2003/05/soap-envelope’));
echo «\n\n»;
// Now you can use XPATH to go to specific nodes
$result = $oXML->xpath(‘//res:Body/LoginResponse/LoginResult’);
foreach ($result as $node){
print_r($node);
}
// convierte xml a json
$json = json_encode($result);
print_r($json);
echo «\n\n»;
// convierte json a array assoc
$vars = json_decode($json, true);
foreach($vars as $valor){
print_r($valor);
}
Que cosas crees que pueda estar pasando por alto o haciendo mal, de manera que me esté costando tanto lograr mi objetivo.
Desde ya, te agradezco cualquier comentario o ayuda.
Saludos !
Hola Jonathan!
Gracias por tus palabras, me alegra que te agraden mis contenidos 🙂
Empezaría por preguntarte qué es lo que no te ha funcionado al usar la clase SoapClient. Ciertamente, para comunicarse con WebServices de tipo SOAP es de lo mejorcito.
Puedes leer algo más en este post.
A simple vista no veo nada extraño, aunque es difícil leer el código así (sin formato).
Mi sugerencia es que intentes nuevamente con SoapClient y, de ser imposible, que intentes con algún debugger, seguro que así podrás encontrar tu problema.
Exitos!
el xml me regresa otro xml ¿como puedo leer ese xml si no conozco su contenido? ya intente guardarlo pero me marca un error
Hola Raúl!
No sé si entiendo bien tu problema… ¿qué significa «el xml me regresa otro xml»? ¿De dónde te lo regresa? ¿Podrías contar un poco más de detalle sobre lo que estás haciendo y lo que intentas lograr?
Si no conoces la estructura del xml que estás tratando de leer se hará algo complicado recorrerlo… podrías intentar algo como una lectura recursiva, arrancando por el elemento raíz e iterar por sus children…
Por último, ¿puedes comentar qué error estás viendo?
Exitos!