Uso básico de SimpleXML. Ejemplo n.º 5 de análisis de datos XML mediante atributos

Uso básico de SimpleXML.  Ejemplo n.º 5 de análisis de datos XML mediante atributos
Uso básico de SimpleXML. Ejemplo n.º 5 de análisis de datos XML mediante atributos

Ahora estudiaremos cómo trabajar con XML. XML es un formato para intercambiar datos entre sitios. Es muy similar a HTML, pero XML permite sus propias etiquetas y atributos.

¿Por qué se necesita XML para el análisis? A veces sucede que el sitio que necesitas analizar tiene una API con la que puedes obtener lo que deseas sin mucho esfuerzo. Por lo tanto, solo un consejo: antes de analizar un sitio, verifique si tiene una API.

¿Qué es una API? Este es un conjunto de funciones con las que puede enviar una solicitud a este sitio y recibir la respuesta deseada. Esta respuesta suele venir en formato XML. Así que comencemos a estudiarlo.

Trabajar con XML en PHP

Digamos que tienes XML. Puede estar en una cadena, almacenarse en un archivo o enviarse a pedido a una URL específica.

Deje que el XML se almacene en una cadena. En este caso, necesita crear un objeto a partir de esta cadena usando nuevo elemento SimpleXML:

$cadena = " kolia 25 1000 "; $xml = nuevo SimpleXMLElement($cadena);

Ahora en nuestra variable $xml Se almacena un objeto con XML analizado. Al acceder a las propiedades de este objeto, puede acceder al contenido de las etiquetas XML. Veremos cómo exactamente a continuación.

Si el XML se almacena en un archivo o se envía accediendo a una URL (que es el caso más frecuente), entonces debería utilizar la función archivo_carga_simplexml, lo que hace que el mismo objeto $xml:

kolia 25 1000

$xml = simplexml_load_file(ruta al archivo o URL);

Métodos de trabajo

En los ejemplos siguientes, nuestro XML se almacena en un archivo o URL.

Sea el siguiente XML:

kolia 25 1000

Obtengamos el nombre, la edad y el salario del empleado:

$xml = simplexml_load_file(ruta al archivo o URL); echo $xml->nombre; //mostrará "Kolya" echo $xml->age; //imprimirá 25 echo $xml->salario; //dará 1000

Como puede ver, el objeto $xml tiene propiedades correspondientes a las etiquetas.

Quizás hayas notado que la etiqueta no aparece en ninguna parte del recurso. Esto se debe a que es la etiqueta raíz. Puede cambiarle el nombre, por ejemplo, a - y nada cambiará:

kolia 25 1000

$xml = simplexml_load_file(ruta al archivo o URL); echo $xml->nombre; //mostrará "Kolya" echo $xml->age; //imprimirá 25 echo $xml->salario; //dará 1000

Sólo puede haber una etiqueta raíz en XML, al igual que la en HTML simple.

Modifiquemos un poco nuestro XML:

kolia 25 1000

En este caso, obtendremos una cadena de solicitudes:

$xml = simplexml_load_file(ruta al archivo o URL); echo $xml->trabajador->nombre; //mostrará "Kolya" echo $xml->trabajador->edad; // generará 25 echo $xml->worker->salary; //dará 1000

Trabajar con atributos

Deje que algunos datos se almacenen en atributos:

Numero 1

$xml = simplexml_load_file(ruta al archivo o URL); echo $xml->trabajador["nombre"]; //mostrará "Kolya" echo $xml->worker["age"]; // generará 25 echo $xml->worker["salary"]; // generará 1000 echo $xml->worker; //mostrará "Número 1"

Etiquetas con guiones

XML permite etiquetas (y atributos) con un guión. En este caso, el acceso a dichas etiquetas se produce así:

kolia Ivánov

$xml = simplexml_load_file(ruta al archivo o URL); echo $xml->trabajador->(nombre); //mostrará "Kolya" echo $xml->trabajador->(apellido); //mostrará "Ivanov"

Bucle

Ahora no tengamos un empleado, sino varios. En este caso, podemos iterar sobre nuestro objeto usando un bucle foreach:

kolia 25 1000 Vasya 26 2000 Pedro 27 3000

$xml = simplexml_load_file(ruta al archivo o URL); foreach ($xml como $trabajador) ( echo $trabajador->nombre; //mostrará "Kolya", "Vasya", "Petya" )

De objeto a matriz normal

Si no te sientes cómodo trabajando con el objeto, puedes convertirlo a una matriz PHP normal usando el siguiente truco:

$xml = simplexml_load_file(ruta al archivo o URL); var_dump(json_decode(json_encode($xml), verdadero));

Más información

Análisis basado en sitemap.xml

A menudo, un sitio tiene un archivo sitemap.xml. Este archivo almacena enlaces a todas las páginas del sitio para facilitar la indexación por parte de los motores de búsqueda (la indexación es esencialmente un análisis del sitio por parte de Yandex y Google).

En general, no deberíamos preocuparnos mucho de por qué se necesita este archivo, lo principal es que, si existe, no es necesario rastrear las páginas del sitio utilizando ningún método complicado, sino simplemente utilizar este archivo.

Cómo verificar la presencia de este archivo: analicemos el sitio site.ru, luego vayamos a site.ru/sitemap.xml en el navegador; si ve algo, entonces está allí, y si no lo ve, entonces ay.

Si hay un mapa del sitio, contiene enlaces a todas las páginas del sitio en formato XML. Tome con calma este XML, analícelo y separe los enlaces a las páginas que necesita de la forma que más le convenga (por ejemplo, analizando la URL, que se describió en el método de la araña).

Como resultado, obtendrá una lista de enlaces para analizar; todo lo que tiene que hacer es ir a ellos y analizar el contenido que necesita.

Lea más sobre el dispositivo sitemap.xml en Wikipedia.

Que deberías hacer después:

Comience a resolver problemas utilizando el siguiente enlace: problemas de la lección.

Cuando hayas decidido todo, pasa a estudiar un nuevo tema.

El análisis XML significa esencialmente recorrer un documento XML y devolver los datos correspondientes. Si bien un número cada vez mayor de servicios web devuelven datos en formato JSON, la mayoría todavía usa XML, por lo que es importante dominar el análisis XML si desea utilizar toda la gama de API disponibles.

Usando la extensión XML simple En PHP, que se agregó nuevamente en PHP 5.0, trabajar con XML es muy fácil y sencillo. En este artículo te mostraré cómo hacerlo.

Conceptos básicos de uso

Comencemos con el siguiente ejemplo. idiomas.xml:


>

> 1972>
> Dennis Ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James Gosling >
>
>

Este documento XML contiene una lista de lenguajes de programación con cierta información sobre cada lenguaje: el año en que se introdujo y el nombre de su creador.

El primer paso es cargar el XML usando las funciones archivo_carga_simplexml(), o simplexml_load_string(). Como sugiere el nombre de las funciones, la primera cargará XML desde un archivo y la segunda cargará XML desde una cadena.

Ambas funciones leen todo el árbol DOM en la memoria y devuelven un objeto. ElementoXML simple. En el ejemplo anterior, el objeto se almacena en la variable $idiomas. Puedes utilizar las funciones var_dump() o imprimir_r() para obtener detalles sobre el objeto devuelto si lo desea.

Objeto SimpleXMLElement
[idioma] => Matriz
[ 0 ] => Objeto SimpleXMLElement
[@attributes] => Matriz
[nombre] => C
[apareció] => 1972
[creador] => Dennis Ritchie
[ 1 ] => Objeto SimpleXMLElement
[@attributes] => Matriz
[nombre] => PHP
[apareció] => 1995
[creador] => Rasmus Lerdorf
[ 2 ] => Objeto SimpleXMLElement
[@attributes] => Matriz
[nombre] => Java
[apareció] => 1995
[creador] => James Gosling
)
)

Este XML contiene un elemento raíz. idiomas, dentro del cual hay tres elementos idioma. Cada elemento de la matriz corresponde a un elemento. idioma en el documento XML.

Puede acceder a las propiedades de un objeto utilizando el operador -> . Por ejemplo, $languages->lang le devolverá un objeto SimpleXMLElement que coincide con el primer elemento. idioma. Este objeto contiene dos propiedades: aparecido y creador.

$idiomas -> idioma [ 0 ] -> apareció;
$idiomas -> idioma [ 0 ] -> creador ;

Mostrar una lista de idiomas y mostrar sus propiedades se puede hacer muy fácilmente usando un bucle estándar como para cada.

foreach ($idiomas -> idioma como $idioma ) (
imprimirf(
"" ,
$idioma ["nombre"],
$lang -> apareció,
$lang -> creador
) ;
}

Observe cómo accedí al nombre del atributo lang del elemento para obtener el nombre del idioma. De esta forma puedes acceder a cualquier atributo de un elemento representado como un objeto SimpleXMLElement.

Trabajar con espacios de nombres

Mientras trabaja con XML de varios servicios web, se encontrará con espacios de nombres de elementos más de una vez. cambiemos nuestro idiomas.xml para mostrar un ejemplo del uso de un espacio de nombres:



xmlns:dc=>

> 1972>
> Dennis Ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James Gosling >
>
>

Ahora el elemento creador cabe en el espacio de nombres corriente continua que apunta a http://purl.org/dc/elements/1.1/. Si intenta imprimir los creadores del idioma usando nuestro código anterior, no funcionará. Para leer espacios de nombres de elementos, debe utilizar uno de los siguientes métodos.

El primer enfoque es utilizar nombres URI directamente en el código al acceder al espacio de nombres del elemento. El siguiente ejemplo muestra cómo se hace esto:

$dc = $idiomas ​​-> idioma [ 1 ] - > niños( "http://purl.org/dc/elements/1.1/") ;
echo $dc -> creador;

Método niños() toma un espacio de nombres y devuelve elementos secundarios que comienzan con un prefijo. Se necesitan dos argumentos, el primero de los cuales es el espacio de nombres XML y el segundo es un argumento opcional cuyo valor predeterminado es FALSO. Si el segundo argumento se establece en VERDADERO, el espacio de nombres se tratará como un prefijo. Si es FALSO, el espacio de nombres se tratará como un espacio de nombres de URL.

El segundo enfoque consiste en leer los nombres de URI del documento y utilizarlos al acceder al espacio de nombres del elemento. En realidad, esta es una mejor manera de acceder a los elementos porque no es necesario estar codificado en el URI.

$espacios de nombres = $idiomas -> getEspacios de nombres (verdadero);
$dc = $idiomas ​​-> idioma [ 1 ] -> niños ( ($espacios de nombres [ "dc" ] );

echo $dc -> creador;

Método Obtener espacios de nombres() devuelve una matriz de nombres de prefijos y sus URI asociados. Acepta un parámetro adicional que por defecto es FALSO. Si lo configuras como verdadero, entonces este método devolverá los nombres utilizados en los nodos padre e hijo. De lo contrario, busca espacios de nombres utilizados sólo en el nodo principal.

Ahora puedes recorrer la lista de idiomas de esta manera:

$idiomas = simplexml_load_file ("idiomas.xml");
$ns = $idiomas -> getNamespaces (verdadero);

foreach ($idiomas -> idioma como $lang ) (
$dc = $lang -> hijos ($ns [ "dc" ] );
imprimirf(
"

%s apareció en %d y fue creado por %s.

" ,
$idioma ["nombre"],
$lang -> apareció,
$dc -> creador
) ;
}

Ejemplo práctico: análisis de un canal de vídeo de YouTube

Veamos un ejemplo que obtiene una fuente RSS de un canal de YouTube y muestra enlaces a todos sus vídeos. Para ello, póngase en contacto con la siguiente dirección:

http://gdata.youtube.com/feeds/api/users/xxx/uploads

La URL devuelve una lista de los vídeos más recientes de un canal determinado en formato XML. Analizaremos el XML y obtendremos la siguiente información para cada vídeo:

  • Enlace al vídeo
  • Miniatura
  • Nombre

Comenzaremos buscando y cargando el XML:

$canal = "nombre_canal";
$url = "http://gdata.youtube.com/feeds/api/users/". $canal. "/cargas" ;
$xml = file_get_contents($url);

$alimentación = simplexml_load_string ($xml);
$ns = $feed -> getNameSpaces (verdadero);

Si observa el feed XML, puede ver que hay varios elementos allí. entidad, cada uno de los cuales almacena información detallada sobre un video específico del canal. Pero sólo utilizamos miniaturas de imágenes, URL de vídeos y títulos. Estos tres elementos son descendientes del elemento. grupo, que a su vez es hijo de entrada:

>

>



Título… >

>

>

Simplemente repasaremos todos los elementos. entrada, y de cada uno de ellos extraeremos la información necesaria. tenga en cuenta que jugador miniatura Y título están en el espacio de nombres de medios. Por tanto, debemos proceder como en el ejemplo anterior. Obtenemos nombres del documento y usamos el espacio de nombres al acceder a los elementos.

foreach ($feed -> entrada como $entrada) (
$grupo = $entrada -> hijos ($ns [ "medios" ] );
$grupo = $grupo -> grupo ;
$thumbnail_attrs = $grupo -> miniatura [ 1 ] -> atributos ();
$imagen = $thumbnail_attrs [ "url" ];
$jugador = $grupo -> jugador -> atributos () ;
$enlace = $jugador [ "url" ] ;
$título = $grupo -> título;
imprimirf( "

" ,
$jugador, $imagen, $título);
}

Conclusión

Ahora que sabes cómo utilizar XML simple Para analizar datos XML, puede mejorar sus habilidades analizando diferentes fuentes XML con diferentes API. Pero es importante considerar que SimpleXML lee todo el DOM en la memoria, por lo que si estás analizando un conjunto de datos grande, es posible que te quedes sin memoria. Para obtener más información sobre SimpleXML, lea la documentación.


Si tienes alguna duda te recomendamos utilizar nuestro


La publicación de este artículo está permitida únicamente con un enlace al sitio web del autor del artículo.

En este artículo mostraré un ejemplo de cómo analizar un archivo XML grande. Si su servidor (alojamiento) no prohíbe aumentar el tiempo de ejecución del script, entonces puede analizar un archivo XML que pese al menos gigabytes; yo personalmente solo analicé archivos de ozono que pesan 450 megabytes.

Al analizar archivos XML grandes, surgen dos problemas:
1. No hay suficiente memoria.
2. No hay suficiente tiempo asignado para ejecutar el script.

El segundo problema con el tiempo se puede solucionar si el servidor no lo prohíbe.
Pero el problema con la memoria es difícil de resolver, incluso si hablamos de su propio servidor, mover archivos de 500 megabytes no es muy fácil y simplemente no es posible aumentar la memoria en hosting y VDS.

PHP tiene varias opciones de procesamiento XML integradas: SimpleXML, DOM, SAX.
Todas estas opciones se describen en detalle en muchos artículos con ejemplos, pero todos los ejemplos demuestran cómo trabajar con un documento XML completo.

Aquí hay un ejemplo, cómo obtener un objeto de un archivo XML.

Ahora puedes procesar este objeto, PERO...
Como puede ver, todo el archivo XML se lee en la memoria y luego todo se analiza en un objeto.
Es decir, todos los datos van a la memoria y si no hay suficiente memoria asignada, el script se detiene.

Esta opción no es adecuada para procesar archivos grandes; necesita leer el archivo línea por línea y procesar estos datos uno por uno.
En este caso, la verificación de validez también se lleva a cabo a medida que se procesan los datos, por lo que es necesario poder revertir, por ejemplo, eliminar todos los datos ingresados ​​en la base de datos en el caso de un archivo XML no válido, o realizar dos pasadas. a través del archivo, primero lea para verificar su validez y luego lea para procesar los datos.

A continuación se muestra un ejemplo teórico de cómo analizar un archivo XML grande.
Este script lee un carácter a la vez de un archivo, recopila estos datos en bloques y los envía al analizador XML.
Este enfoque resuelve completamente el problema de la memoria y no causa carga, pero agrava el problema con el tiempo. Cómo intentar resolver el problema con el tiempo, lea a continuación.

Función webi_xml ($archivo)
{

########
### función de datos

{
imprimir $datos;
}
############################################



{
imprimir $nombre;
print_r($atributos);
}


## función de etiqueta de cierre
función endElement ($ analizador, $ nombre)
{
imprimir $nombre;
}
############################################

($xml_parser, "datos");

// abre el archivo
$fp = fopen($archivo, "r");

$perviy_vxod = 1 ; $datos = "" ;



{

$simvol = fgetc ($fp); $datos .= $simvol ;


if($simvol != ">" ) ( continuar;)


eco "

romper;
}

$datos = "" ;
}
fclose($fp);

Webi_xml("1.xml");

?>

En este ejemplo, puse todo en una función webi_xml() y en la parte inferior puedes ver su llamada.
El script en sí consta de tres funciones principales:
1. Una función que detecta la apertura de la etiqueta startElement()
2. Una función que captura la etiqueta endElement() de cierre
3. Y la función de recepción de datos data().

Supongamos que el contenido del archivo 1.xml es una receta.



< title >pan sencillo
< ingredient amount = "3" unit = "стакан" >Harina
< ingredient amount = "0.25" unit = "грамм" >Levadura
< ingredient amount = "1.5" unit = "стакан" >Agua tibia
< ingredient amount = "1" unit = "чайная ложка" >Sal
< instructions >
< step > Mezclar todos los ingredientes y amasar bien..
< step > Cubrir con un paño y dejar reposar una hora en una habitación cálida..
< step > Amasar de nuevo, colocar en una bandeja para hornear y meter al horno..
< step > Visitar sitio sitio


Empezamos todo llamando a la función general webi_xml ("1.xml" );
A continuación, el analizador comienza con esta función y convierte todos los nombres de etiquetas a mayúsculas para que todas las etiquetas tengan el mismo caso.

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, verdadero);

Ahora indicamos qué funciones funcionarán para captar la apertura de una etiqueta, cerrarla y procesar datos.

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "datos");

Luego viene la apertura del archivo especificado, iterando a través del archivo un carácter a la vez y cada carácter se agrega a la variable de cadena hasta que se encuentra el carácter. > .
Si este es el primer acceso al archivo, en el camino se eliminará todo lo que no sea necesario al principio del archivo, todo lo que viene antes. , esta es la etiqueta con la que debería comenzar XML.
Por primera vez, una variable de cadena contendrá una cadena

Y enviarlo al desensamblador.
xml_parse ($xml_parser, $datos, feof ($fp));
Después de procesar los datos, la variable de cadena se restablece y la recopilación de datos en una cadena comienza nuevamente y la cadena se forma por segunda vez.

En el tercero
</b><br>en el cuarto <br><b>pan sencillo

Tenga en cuenta que una variable de cadena siempre se forma a partir de una etiqueta completa > y no es necesario enviar al ladrón una etiqueta abierta y cerrada con datos, por ejemplo
pan sencillo
Es importante que este controlador reciba una etiqueta completa e ininterrumpida, al menos una etiqueta abierta y en el siguiente paso una etiqueta cerrada, o recibir inmediatamente 1000 líneas de un archivo, no importa, lo principal es que la etiqueta no se rompe, por ejemplo

le>pan simple
De esta manera, es imposible enviar datos al controlador, ya que la etiqueta está rota.
Puede idear su propio método para enviar datos al controlador, por ejemplo, recopilar 1 megabyte de datos y enviarlo al controlador para aumentar la velocidad, solo asegúrese de que las etiquetas siempre estén completas y que los datos se puedan romper.
Simple</b><br><b>pan

Así, en las partes que desee, podrá enviar un archivo de gran tamaño al procesador.

Ahora veamos cómo se procesan estos datos y cómo obtenerlos.

Comencemos con la función de etiquetas de apertura. startElement ($analizador, $nombre, $atributos)
Supongamos que el procesamiento ha llegado a la línea
< ingredient amount = "3" unit = "стакан" >Harina
Entonces dentro de la función la variable $nombre será igual a ingrediente es decir, el nombre de la etiqueta abierta (aún no ha llegado a cerrar la etiqueta).
También en este caso, estará disponible una matriz de atributos de esta etiqueta $attrs, que contendrá datos cantidad = "3" y unidad = "vidrio".

Después de esto, los datos de la etiqueta abierta fueron procesados ​​por la función datos ($analizador, $datos)
La variable $data contendrá todo lo que esté entre las etiquetas de apertura y cierre, en nuestro caso este es el texto Muka

Y finaliza el procesamiento de nuestra cadena por parte de la función. endElement ($analizador, $nombre)
Este es el nombre de la etiqueta cerrada, en nuestro caso $nombre será igual a ingrediente

Y después todo volvió a dar vueltas.

El ejemplo anterior solo demuestra el principio del procesamiento XML, pero para una aplicación real es necesario modificarlo.
Por lo general, debe analizar XML de gran tamaño para ingresar datos en la base de datos y, para procesar correctamente los datos, necesita saber a qué etiqueta abierta pertenecen los datos, qué nivel de anidamiento de etiquetas y qué etiquetas están abiertas en la jerarquía superior. Con esta información podrás procesar el archivo correctamente sin ningún problema.
Para hacer esto, debe introducir varias variables globales que recopilarán información sobre etiquetas abiertas, anidamiento y datos.
Aquí tienes un ejemplo que puedes utilizar

Función webi_xml ($archivo)
{
global $webi_profundidad; // contador para rastrear la profundidad de anidamiento
$webi_profundidad = 0;
global $webi_tag_open; // contendrá una serie de etiquetas actualmente abiertas
$webi_tag_open = matriz();
global$webi_data_temp; // esta matriz contendrá los datos de una etiqueta

####################################################
### función de datos
datos de función ($ analizador, $ datos)
{
global $webi_profundidad;
global $webi_tag_open;
global$webi_data_temp;
// agrega datos a la matriz que indican el anidamiento y la etiqueta actualmente abierta
$webi_data_temp [ $webi_profundidad ][ $webi_tag_open [ $webi_profundidad ]][ "datos" ].= $datos ;
}
############################################

####################################################
### función de etiqueta de apertura
función startElement ($parser, $nombre, $attrs)
{
global $webi_profundidad;
global $webi_tag_open;
global$webi_data_temp;

// si el nivel de anidamiento ya no es cero, entonces ya hay una etiqueta abierta
// y los datos que contiene ya están en la matriz, puedes procesarlos
si ($webi_profundidad)
{




" ;

imprimir "
" ;
print_r($webi_tag_open); // conjunto de etiquetas abiertas
imprimir "


" ;

//después de procesar los datos, los eliminamos para liberar memoria
unset($GLOBALS [ "webi_data_temp" ][ $webi_profundidad ]);
}

// ahora se abre la siguiente etiqueta y se producirá un procesamiento adicional en el siguiente paso
$webi_profundidad++; // aumentar el anidamiento

$webi_tag_open [ $webi_profundidad ]= $nombre ; // agrega una etiqueta abierta a la matriz de información
$webi_data_temp [ $webi_profundidad ][ $nombre ][ "atributos" ]= $atributos ; // ahora agrega atributos de etiqueta

}
###############################################

#################################################
## función de etiqueta de cierre
función endElement ($ analizador, $ nombre) (
global $webi_profundidad;
global $webi_tag_open;
global$webi_data_temp;

// El procesamiento de datos comienza aquí, por ejemplo, agregarlos a la base de datos, guardarlos en un archivo, etc.
// $webi_tag_open contiene una cadena de etiquetas abiertas por nivel de anidamiento
// por ejemplo $webi_tag_open[$webi_ Depth] contiene el nombre de la etiqueta abierta cuya información se está procesando actualmente
// $webi_ Depth nivel de anidamiento de etiquetas
// $webi_data_temp[$webi_profundidad][$webi_tag_open[$webi_profundidad]]["attrs"] matriz de atributos de etiqueta
// $webi_data_temp[$webi_profundidad][$webi_tag_open[$webi_profundidad]]["datos"] datos de etiqueta

Imprimir "datos". $webi_tag_open [ $webi_profundidad ]. "--" .($webi_data_temp [ $webi_profundidad ][ $webi_tag_open [ $webi_profundidad ]][ "datos" ]). "
" ;
print_r ($webi_data_temp [ $webi_profundidad ][ $webi_tag_open [ $webi_profundidad ]][ "atributos" ]);
imprimir "
" ;
print_r($webi_tag_open);
imprimir "


" ;

Desarmado($GLOBALS [ "webi_data_temp" ]); // después de procesar los datos, borramos todo el array con los datos, ya que la etiqueta se cerró
unset($GLOBALS [ "webi_tag_open" ][ $webi_profundidad ]); // elimina información sobre esta etiqueta abierta... desde que cerró

$webi_profundidad --; // reducir el anidamiento
}
############################################

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, verdadero);

// indica qué funciones funcionarán al abrir y cerrar etiquetas
xml_set_element_handler($xml_parser, "startElement", "endElement");

// especifica una función para trabajar con datos
xml_set_character_data_handler($xml_parser, "datos");

// abre el archivo
$fp = fopen($archivo, "r");

$perviy_vxod = 1 ; // bandera para verificar la primera entrada en el archivo
$datos = "" ; // aquí recopilamos datos del archivo en partes y los enviamos al analizador xml

// bucle hasta encontrar el final del archivo
mientras (! feof ($fp) y $fp)
{
$simvol = fgetc ($fp); // lee un carácter del archivo
$datos .= $simvol ; // agrega este caracter a los datos a enviar

// si el carácter no es la etiqueta final, entonces regresa al principio del ciclo y agrega otro carácter a los datos, y así sucesivamente hasta encontrar la etiqueta final
if($simvol != ">" ) ( continuar;)
// si se encontró la etiqueta de cierre, ahora enviaremos estos datos recopilados para su procesamiento

// verificamos si esta es la primera entrada en el archivo, luego eliminaremos todo lo que está antes de la etiqueta// ya que a veces puedes encontrar basura antes del comienzo del XML (editores torpes o el archivo fue recibido mediante un script de otro servidor)
if($perviy_vxod) ($datos = strstr ($datos, "

// ahora lanzamos los datos al analizador xml
si (! xml_parse ($xml_parser, $datos, feof ($fp))) (

// aquí puedes procesar y recibir errores de validez...
// tan pronto como se encuentra un error, el análisis se detiene
eco "
Error XML: " . xml_error_string(xml_get_error_code($xml_parser));
eco "en la línea" . xml_get_current_line_number ($xml_parser);
romper;
}

// después del análisis, descarta los datos recopilados para el siguiente paso del ciclo.
$datos = "" ;
}
fclose($fp);
xml_parser_free($xml_parser);
// eliminando variables globales
unset($GLOBALS [ "webi_profundidad" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);

Webi_xml("1.xml");

?>

Todo el ejemplo va acompañado de comentarios, ahora prueba y experimenta.
Tenga en cuenta que en la función de trabajar con datos, los datos no se insertan simplemente en una matriz, sino que se agregan usando " .=" ya que es posible que los datos no lleguen en su totalidad y, si solo realiza una tarea, de vez en cuando recibirá los datos en fragmentos.

Bueno, eso es todo, ahora hay suficiente memoria para procesar un archivo de cualquier tamaño, pero el tiempo de ejecución del script se puede aumentar de varias maneras.
Insertar una función al principio del script.
set_time_limit(6000);
o
ini_set ("max_execution_time", "6000");

O agregue texto al archivo .htaccess
php_value max_execution_time 6000

Estos ejemplos aumentarán el tiempo de ejecución del script a 6000 segundos.
Puede aumentar el tiempo de esta manera solo cuando el modo seguro está desactivado.

Si tiene acceso para editar php.ini, puede aumentar el tiempo usando
max_execution_time = 6000

Por ejemplo, en el alojamiento Masterhost, al momento de escribir este artículo, está prohibido aumentar el tiempo del script, a pesar de que el modo seguro esté desactivado, pero si eres un profesional, puedes crear tu propia compilación PHP en Masterhost, pero eso no es el tema de este artículo.

Nivel 1. Pasar la prueba (interacción con el circuito de prueba GIS GMP) Dirección del servicio de prueba #GIS GMP:
gisgmp.wsdlLocation=http://213.59.255.182:7777/gateway/services/SID0003663?wsdl
gisgmp.wsdlLocation.endPoint=http://213.59.255.182:7777/gateway/services/SID0003663
Esta dirección está registrada en la configuración del SP. Además, debe registrarla en el archivo de configuración de registro, especificando el valor. RASTRO. Después de ingresar los valores especificados, debe iniciar el SP y el cliente ACC (reiniciar si ya se inició). A continuación, desde el ROR o la Oficina de Contabilidad/AU Aplicación para el pago de fondos, debe realizar la acción. “Crear información de pago”, si se pasan los controles del sistema, se creará la información sobre el pago. Que luego será necesario descargar.
Después de la carga, debe verificar el estado mediante la acción "Solicitar estado de procesamiento". Después de lo cual la información de pago de ED cambia al estado "Aceptado por GIS GMP" -...

Dado: Tabla MSG (mensajes) con muchas entradas.
CREATETABLEmsg(idINTEGERNOTNULLPRIMARYKEY,descriptionCHAR(50)NOTNULL, date_createDATE);
Tarea:
Es necesario borrar la tabla de datos/
Solución: Hay varias formas de solucionar este problema. A continuación se muestra una descripción y ejemplo de cada uno de ellos.
La forma más fácil ( primera opción) - ejecución del operador de eliminación de registros. Cuando lo ejecutes, verás el resultado (cuántos registros se eliminaron). Algo útil cuando necesita saber con certeza y comprender si se han eliminado los datos correctos. PERO tiene desventajas en comparación con otras opciones para resolver el problema.

DELETE FROMmsg;--Borra todas las filas de la tabla --Elimina todas las filas con fecha de creación "2019.02.01" BORRAR DE msg WHEREdate_create="2019.02.01";

Segunda opción. Usar la declaración DML para borrar todas las filas de una tabla.
TRUNCATETABLEmsg;
Hay varias características al usar este operador:
No está en Firebird, por lo que usamos la primera y tercera opción Después...

Direcciones actuales para solicitudes al SMEV 3.0 Le recordamos que, de acuerdo con la información previamente publicada en el Portal Tecnológico SMEV 3.0, es necesario utilizar las direcciones actuales para el Servicio Electrónico Unificado:
la dirección del servicio electrónico unificado del entorno de desarrollo SMEV 3.0, correspondiente al esquema 1.1 - http://smev3-d.test.gosuslugi.ru:7500/smev/v1.1/ws?wsdl, y el servicio también estar disponible en

El lenguaje de marcado extensible XML es un conjunto de reglas para codificar documentos en un formato legible por máquina. XML es un formato popular para intercambiar datos en Internet. Los sitios que actualizan frecuentemente su contenido, como sitios de noticias o blogs, a menudo proporcionan una fuente XML para que los programas externos estén al tanto de los cambios de contenido. Enviar y analizar datos XML es una tarea común para las aplicaciones conectadas a la red. Este tutorial explica cómo analizar documentos XML y utilizar sus datos.

Elegir un analizador

Análisis de canales

El primer paso para analizar un feed es decidir qué campos de datos le interesan. El analizador extrae los campos dados e ignora todo lo demás.

A continuación se muestra un fragmento del canal que se explorará en la aplicación de ejemplo. Cada publicación en StackOverflow.com aparece en un feed como una etiqueta de entrada, que contiene varias subetiquetas:

preguntas más recientes etiquetadas android ... ... http://stackoverflow.com/q/9439999 0 ¿Dónde está mi archivo de datos? acantilado2310 http://stackoverflow.com/users/1128925 2012-02-25T00:30:54Z 2012-02-25T00:30:54Z

Tengo una aplicación que requiere un archivo de datos...

... ...

La aplicación de ejemplo recupera datos de la etiqueta de entrada y sus subetiquetas título, enlace y resumen.

Creando una instancia de analizador

El siguiente paso es crear una instancia del analizador e iniciar el proceso de análisis. Este fragmento inicializa el analizador para que no maneje espacios de nombres y use el InputStream proporcionado como entrada. El proceso de análisis comienza con una llamada a nextTag() y llama al método readFeed(), que recupera y procesa los datos que le interesan a la aplicación:

Clase pública StackOverflowXmlParser ( // No usamos espacios de nombres private static final String ns = null; public List parse(InputStream in) lanza XmlPullParserException, IOException ( try ( XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES , falso); parser.setInput(in, null); parser.nextTag(); return readFeed(parser) finalmente ( in.close(); ) ... )

Restar canal

El método readFeed() realiza el trabajo real de procesar el feed. Los elementos marcados con la etiqueta "entrada" son el punto de partida para el procesamiento recursivo del canal. Si la siguiente etiqueta no es una etiqueta de entrada, se omite. Después de que todo el "feed" se haya procesado de forma recursiva, readFeed() devuelve una Lista que contiene las entradas (incluidos los elementos de datos anidados) que se recuperan del feed. Luego, el analizador devuelve esta lista.

Lista privada readFeed (analizador XmlPullParser) arroja XmlPullParserException, IOException (entradas de lista = nueva ArrayList (); parser.require(XmlPullParser.START_TAG, ns, "feed"); while (parser.next()! = XmlPullParser.END_TAG) (si (parser.getEventType() != XmlPullParser.START_TAG) ( continuar; ) String name = parser.getName() // Comienza buscando la etiqueta de entrada if (name.equals("entry")) (entradas.add( readEntry(analizador)); else ( skip(analizador); ) ) devuelve entradas;

análisis XML

Los pasos para analizar el feed XML son los siguientes:

Este fragmento muestra cómo el analizador analiza la entrada, el título, el enlace y el resumen.

Entrada de clase estática pública (título de cadena final público; enlace de cadena final público; resumen de cadena final público; entrada privada (título de cadena, resumen de cadena, enlace de cadena) ( this.title = título; this.summary = resumen; this.link = enlace ; ) ) // Analiza el contenido de una entrada. Si encuentra un título, resumen o etiqueta de enlace, entréguelos // a sus respectivos métodos de "lectura" para su procesamiento. De lo contrario, omita la etiqueta. entrada privada readEntry (analizador XmlPullParser) lanza XmlPullParserException, IOException (parser.require(XmlPullParser.START_TAG, ns, "entry"); Título de cadena = nulo; Resumen de cadena = nulo; Enlace de cadena = nulo; while (parser.next()! = XmlPullParser.END_TAG) ( if (parser.getEventType() != XmlPullParser.START_TAG) ( continuar; ) Nombre de cadena = parser.getName(); if (name.equals("title")) ( title = readTitle(parser) ; ) else if (nombre.equals("resumen")) ( resumen = readSummary(analizador); ) else if (name.equals("enlace")) ( enlace = readLink(analizador); ) else ( skip(analizador) ; ) ) return new Entry(título, resumen, enlace) // Procesa etiquetas de título en el feed. readTitle de cadena privada (analizador XmlPullParser) lanza IOException, XmlPullParserException (parser.require(XmlPullParser.START_TAG, ns, "título"); Título de cadena = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "título"); devolver título; ) // Procesa etiquetas de enlace en el feed. cadena privada readLink (analizador XmlPullParser) lanza IOException, XmlPullParserException (String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); String relType = parser.getAttributeValue(null , "rel"); if (tag.equals("enlace")) ( if (relType.equals("alternate"))( enlace = parser.getAttributeValue(null, "href"); parser.nextTag(); ) ) parser.require(XmlPullParser.END_TAG, ns, "link"); // Procesa etiquetas de resumen en el feed. cadena privada readSummary (analizador XmlPullParser) lanza IOException, XmlPullParserException ( parser.require (XmlPullParser.START_TAG, ns, "summary"); resumen de cadena = readText (parser); parser.require (XmlPullParser.END_TAG, ns, "summary"); return resumen; ) // Para las etiquetas título y resumen, extrae sus valores de texto. cadena privada readText (analizador XmlPullParser) lanza IOException, XmlPullParserException ( resultado de cadena = ""; if (parser.next() == XmlPullParser.TEXT) (resultado = parser.getText(); parser.nextTag(); ) devuelve resultado; ) ... )

Saltarse elementos que no necesitas

En uno de los pasos de análisis XML descritos anteriormente, el analizador omite etiquetas que no nos interesan. A continuación se muestra el código del analizador para el método skip():

Private void skip(analizador XmlPullParser) lanza XmlPullParserException, IOException ( if (parser.getEventType() != XmlPullParser.START_TAG) ( throw new IllegalStateException(); ) int profundidad = 1; while (profundidad! = 0) ( switch (parser. next()) ( caso XmlPullParser.END_TAG: profundidad--; ruptura; caso XmlPullParser.START_TAG: profundidad++; ruptura; ) ) )

Así es como funciona:

  • El método genera una excepción si el evento actual no es START_TAG.
  • Consume START_TAG y todos los eventos hasta END_TAG.
  • Para asegurarse de que se detenga en el END_TAG correcto y no en la primera etiqueta después del START_TAG original, realiza un seguimiento de la profundidad de anidamiento.

Por lo tanto, si el elemento actual tiene elementos anidados, el valor de profundidad no será 0 hasta que el analizador haya procesado todos los eventos entre el START_TAG original y su END_TAG correspondiente. Por ejemplo, considere cómo pasa el analizador. un elemento que tiene 2 elementos anidados, Y :

  • En el primer paso por el bucle while, la siguiente etiqueta que encuentra el analizador después esto es START_TAG para
  • En el segundo paso por el bucle while, la siguiente etiqueta que encuentra el analizador es END_TAG
  • En el tercer paso por el bucle while, la siguiente etiqueta que encuentra el analizador es START_TAG . El valor de profundidad aumenta a 2.
  • En el cuarto paso por el bucle while, la siguiente etiqueta que encuentra el analizador es END_TAG. El valor de profundidad se reduce a 1.
  • En el quinto y último paso por el ciclo while, la siguiente etiqueta que encuentra el analizador es END_TAG. El valor de profundidad se reduce a 0, lo que indica que el elemento se omitió con éxito.

Procesamiento de datos XML

La aplicación de ejemplo recibe y analiza una fuente XML en una AsyncTask. El procesamiento se produce fuera del hilo principal de la interfaz de usuario. Cuando se completa el procesamiento, la aplicación actualiza la interfaz de usuario en la actividad principal (NetworkActivity).

En el siguiente fragmento, el método loadPage() hace lo siguiente:

  • Inicializa una variable de cadena con una URL que apunta a una fuente XML.
  • Si la configuración del usuario y la conexión de red lo permiten, llama a new DownloadXmlTask().execute(url) . Esto crea un nuevo objeto DownloadXmlTask ​​(subclase AsyncTask) y ejecuta su método ejecutar(), que descarga y analiza la canalización y devuelve un resultado de cadena que se mostrará en la interfaz de usuario.
la clase pública NetworkActivity extiende la actividad (cadena final estática pública WIFI = "Wi-Fi"; cadena final estática pública ANY = "cualquiera"; cadena final estática privada URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort =newest"; // Si hay una conexión Wi-Fi. private static boolean wifiConnected = false; // Si hay una conexión móvil. private static boolean mobileConnected = false; // Si se debe actualizar la pantalla. public static boolean actualizarDisplay = true; public static String sPref = null ... // Utiliza AsyncTask para descargar el feed XML de stackoverflow.com public void loadPage() (if((sPref.equals(ANY)) && (wifiConnected || mobileConnected) ) ( new DownloadXmlTask().execute(URL); ) else if ((sPref.equals(WIFI)) && (wifiConnected)) ( new DownloadXmlTask().execute(URL); ) else ( // mostrar error ) )
  • doInBackground() ejecuta el método loadXmlFromNetwork(). Pasa la URL del canal como parámetro. El método loadXmlFromNetwork() recibe y procesa el canal. Cuando termina de procesar, devuelve la cadena resultante.
  • onPostExecute() toma la cadena devuelta y la muestra en la interfaz de usuario.
// Implementación de AsyncTask utilizada para descargar feeds XML desde stackoverflow.com. la clase privada DownloadXmlTask ​​​​extiende AsyncTask ( @Override protected String doInBackground(String... urls) ( try ( return loadXmlFromNetwork(urls); ) catch (IOException e) ( return getResources().getString(R.string.connection_error); ) catch (XmlPullParserException e) ( return getResources().getString(R.string.xml_error); ) @Override protected void onPostExecute(Resultado de cadena) ( setContentView(R.layout.main); // Muestra la cadena HTML en la interfaz de usuario a través de WebView WebView myWebView = ( WebView) findViewById(R.id.webview); myWebView.loadData(resultado, "texto/html", nulo))

A continuación se muestra el método loadXmlFromNetwork() que se llama desde DownloadXmlTask. Hace lo siguiente:

  1. Crea una instancia de StackOverflowXmlParser. También crea variables para objetos de entrada de lista, y título, URL y resumen, para almacenar los valores extraídos del feed XML para estos campos.
  2. Llama a downloadUrl() que descarga el canal y lo devuelve como InputStream.
  3. Utiliza StackOverflowXmlParser para analizar un InputStream. StackOverflowXmlParser completa las entradas de la lista con datos del feed.
  4. Procesa la lista de entradas y combina los datos del canal con el marcado HTML.
  5. Devuelve la cadena HTML que se muestra en la interfaz de usuario de la actividad principal, AsyncTask, en el método onPostExecute().
// Carga XML desde stackoverflow.com, lo analiza y lo combina con // el marcado HTML. Devuelve una cadena HTML. cadena privada loadXmlFromNetwork(String urlString) lanza XmlPullParserException, IOException (InputStream stream = null; // Crea una instancia del analizador StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser(); Lista entradas = nulo; Título de cadena = nulo; URL de cadena = nula; Resumen de cadena = nulo; Calendario ahora mismo = Calendar.getInstance(); Formato DateFormat = new SimpleDateFormat("MMM dd h:mmaa"); // Comprueba si el usuario configuró la preferencia para incluir texto de resumen SharedPreferences sharePrefs = PreferenceManager.getDefaultSharedPreferences(this); pref booleana = sharePrefs.getBoolean("summaryPref", false); StringBuilder htmlString = nuevo StringBuilder(); htmlString.append("

" + getResources().getString(R.string.page_title) + "

"); htmlString.append(" " + getResources().getString(R.string.updated) + " " + formatter.format(rightNow.getTime()) + ""); try ( stream = downloadUrl(urlString); entradas = stackOverflowXmlParser.parse(stream); // Se asegura de que InputStream esté cerrado después de que la aplicación // termine de usarla. ) finalmente ( if (stream != null) ( stream.close(); ) // StackOverflowXmlParser devuelve una lista (llamada "entradas") de objetos de entrada. // Cada objeto de entrada representa una única publicación en el feed XML // Esta sección procesa la lista de entradas para combinar cada una. entrada con marcado HTML. // Cada entrada se muestra en la interfaz de usuario como un enlace que incluye opcionalmente // un resumen de texto para (Entrada entrada: entradas) ( htmlString.append("

" + entrada.título + "

"); // Si el usuario establece la preferencia para incluir texto de resumen, // lo agrega a la pantalla. if (pref) ( htmlString.append(entry.summary); ) ) return htmlString.toString(); ) // Dada una representación de cadena de una URL, configura una conexión y obtiene // un flujo de entrada. inputStream privado downloadUrl(String urlString) lanza IOException ( URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection() ; conn.setReadTimeout(10000 /* milisegundos */); conn.setConnectTimeout(15000 /* milisegundos */); conn.setRequestMethod("GET"); // Inicia la consulta conn.connect( ); );