• Publicidad

Procesar archivo XML gigantesco en Perl

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Procesar archivo XML gigantesco en Perl

Notapor danimera » 2013-01-18 14:40 @653

Resulta que tengo un archivo collada .dae. Es un xml de los programas de 3D Maya y 3d Studio.

Pero resulta que tengo que pasar una información a una DB y este archivo pesa nada más y nada menos que 250 Mb y tiene unas 8 600 000 de líneas...

Si lo recorro en un while() demora casi 18 minutos solo para recorrerlo. Si lo quiero pasar a un array, fuera de que me consume 1 Gb de RAM me demora 40 minutos...

Quería usar XML::Simple para poder leer la estructura y sacar la información que necesito pero jamás termina de hacerlo.

Ahora podría filtrar el archivo ya que la información que necesita está dentro de una etiqueta especial y es por la línea más o menos 8 millones...

En sí tengo una solución, pero no sé en Perl si hay algo más cómodo para trabajar con estos archivos tan grandes...
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Publicidad

Re: Procesar archivo XML gigantesco en Perl

Notapor explorer » 2013-01-18 15:15 @677

Si el XML está más o menos bien formado (formateado), entonces la marca que buscamos, inicio y final, estarán cada uno en una línea distinta.

Con el operador rango puedes restringir la búsqueda a solo esas líneas.

Lo que no entiendo es por qué te tarda tanto en leer los ocho millones de líneas en tanto tiempo...

¿No será que estás usando Windows, verdad?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesar archivo XML gigantesco en Perl

Notapor danimera » 2013-01-18 15:53 @704

Sí, claro, uso Windows... Ahora, el alojamiento para donde va es Linux pero pues si es más rápido trato ahí, pero me da miedo que colapse, pues son varios archivos, no es solo uno, y no están en una posición definida, solo conozco el nombre de la etiqueta que enmarca la información que necesito.
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Re: Procesar archivo XML gigantesco en Perl

Notapor explorer » 2013-01-18 17:11 @757

Y ¿qué versión de Perl tienes en tu Windows?

¿Cuántas operaciones realizas dentro del bucle while() para que tarde 18 minutos?

¿Cuánto tarda en leer el archivo si el while() no realiza ninguna operación -solo leer las líneas-?

Da igual que la etiqueta se componga de una marca de apertura y otra de cierre, o una sola, o en dos líneas o en una sola. Con el operador rango la puedes sacar fácilmente. Y si sabes que no se va a repetir más que solo una vez a lo largo del archivo, cuando terminas de leerla, haces un last y sales inmediatamente del bucle.

Edito: en mi ordenador (1.5 Ghz AMD Athlon 64 Processor 3000+) con un Linux 3.4.11 x86_64, soy capaz de procesar 10 157 872 líneas de un xml, en poco más de 40 s (el xml consiste en 4 copias consecutivas de la ejecución de mame -listxml).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesar archivo XML gigantesco en Perl

Notapor danimera » 2013-01-18 17:35 @774

Uso Active State Perl v5.16, creo...

Sólo necesito sacar el dato de la etiqueta <node id="elemento1"> y guardarla en la DB.

Pero hasta ahora no hago nada, solo tengo un simple código que... hummm... es mentira:
se demoró eso imprimiendo cada línea en consola. Creo que por eso demoró 17 minutos...

La otra forma es que me gustaría mejor pasar el XML a una estructura de datos...

Lo único que sé es que es un árbol de N niveles CON agrupaciones que pueden tener X cantidad de nodos, y pues, me gustaría lograr pasar todo a un array y lograr de ahí leer esa información más fácil...

Ejemplo del archivo:
La información está dentro de la etiqueta <visual_scene id="" name="">.
Me interesa los <node> pero hay <node> padres e hijos y así mismo debe insertarlo en la BD... darle un id al padre para relacionar con los hijos, etc....

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <library_visual_scenes>
  2.     <visual_scene id="" name="">
  3.       <node name="group" id="group" sid="group">
  4.         <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  5.         <extra>
  6.           <technique profile="FCOLLADA">
  7.             <visibility>1.000000</visibility>
  8.           </technique>
  9.         </extra>
  10.         <node name="grp_geometrias01" id="grp_geometrias01" sid="grp_geometrias01">
  11.           <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  12.           <extra>
  13.             <technique profile="FCOLLADA">
  14.               <visibility>1.000000</visibility>
  15.             </technique>
  16.           </extra>
  17.           <node name="grp_circulos01" id="grp_circulos01" sid="grp_circulos01">
  18.             <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  19.             <extra>
  20.               <technique profile="FCOLLADA">
  21.                 <visibility>1.000000</visibility>
  22.               </technique>
  23.             </extra>
  24.             <node name="pSphere2" id="pSphere2" sid="pSphere2">
  25.               <matrix sid="matrix">1.000000 0.000000 0.000000 9.018759 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -2.667085 0.000000 0.000000 0.000000 1.000000</matrix>
  26.               <instance_geometry url="#pSphere2-lib">
  27.                 <bind_material>
  28.                   <technique_common>
  29.                     <instance_material symbol="lambert2" target="#lambert2"/>
  30.                   </technique_common>
  31.                 </bind_material>
  32.               </instance_geometry>
  33.               <extra>
  34.                 <technique profile="FCOLLADA">
  35.                   <visibility>1.000000</visibility>
  36.                 </technique>
  37.               </extra>
  38.             </node>
  39.             <node name="pSphere1" id="pSphere1" sid="pSphere1">
  40.               <matrix sid="matrix">1.000000 0.000000 0.000000 -7.182602 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 9.450900 0.000000 0.000000 0.000000 1.000000</matrix>
  41.               <instance_geometry url="#pSphere1-lib">
  42.                 <bind_material>
  43.                   <technique_common>
  44.                     <instance_material symbol="lambert2" target="#lambert2"/>
  45.                   </technique_common>
  46.                 </bind_material>
  47.               </instance_geometry>
  48.               <extra>
  49.                 <technique profile="FCOLLADA">
  50.                   <visibility>1.000000</visibility>
  51.                 </technique>
  52.               </extra>
  53.             </node>
  54.           </node>
  55.           <node name="grp_cilindros01" id="grp_cilindros01" sid="grp_cilindros01">
  56.             <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  57.             <extra>
  58.               <technique profile="FCOLLADA">
  59.                 <visibility>1.000000</visibility>
  60.               </technique>
  61.             </extra>
  62.             <node name="pCylinder1" id="pCylinder1" sid="pCylinder1">
  63.               <matrix sid="matrix">1.000000 0.000000 0.000000 36.367127 0.000000 1.000000 0.000000 15.203651 0.000000 0.000000 1.000000 -34.329298 0.000000 0.000000 0.000000 1.000000</matrix>
  64.               <instance_geometry url="#pCylinder1-lib">
  65.                 <bind_material>
  66.                   <technique_common>
  67.                     <instance_material symbol="lambert2" target="#lambert2"/>
  68.                   </technique_common>
  69.                 </bind_material>
  70.               </instance_geometry>
  71.               <extra>
  72.                 <technique profile="FCOLLADA">
  73.                   <visibility>1.000000</visibility>
  74.                 </technique>
  75.               </extra>
  76.             </node>
  77.             <node name="pCylinder2" id="pCylinder2" sid="pCylinder2">
  78.               <matrix sid="matrix">1.000000 0.000000 0.000000 64.502382 0.000000 1.000000 0.000000 13.311090 0.000000 0.000000 1.000000 -42.815139 0.000000 0.000000 0.000000 1.000000</matrix>
  79.               <instance_geometry url="#pCylinder2-lib">
  80.                 <bind_material>
  81.                   <technique_common>
  82.                     <instance_material symbol="lambert2" target="#lambert2"/>
  83.                   </technique_common>
  84.                 </bind_material>
  85.               </instance_geometry>
  86.               <extra>
  87.                 <technique profile="FCOLLADA">
  88.                   <visibility>1.000000</visibility>
  89.                 </technique>
  90.               </extra>
  91.             </node>
  92.           </node>
  93.         </node>
  94.         <node name="grp_geometrias02" id="grp_geometrias02" sid="grp_geometrias02">
  95.           <matrix sid="matrix">1.000000 0.000000 0.000000 53.667200 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  96.           <extra>
  97.             <technique profile="FCOLLADA">
  98.               <visibility>1.000000</visibility>
  99.             </technique>
  100.           </extra>
  101.           <node name="grp_circulos01_ncl1_1" id="grp_circulos01_ncl1_1" sid="grp_circulos01_ncl1_1">
  102.             <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  103.             <extra>
  104.               <technique profile="FCOLLADA">
  105.                 <visibility>1.000000</visibility>
  106.               </technique>
  107.             </extra>
  108.             <node name="pSphere2_ncl1_1" id="pSphere2_ncl1_1" sid="pSphere2_ncl1_1">
  109.               <matrix sid="matrix">1.000000 0.000000 0.000000 9.018759 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -2.667085 0.000000 0.000000 0.000000 1.000000</matrix>
  110.               <instance_geometry url="#pSphere2_ncl1_1-lib">
  111.                 <bind_material>
  112.                   <technique_common>
  113.                     <instance_material symbol="lambert2" target="#lambert2"/>
  114.                   </technique_common>
  115.                 </bind_material>
  116.               </instance_geometry>
  117.               <extra>
  118.                 <technique profile="FCOLLADA">
  119.                   <visibility>1.000000</visibility>
  120.                 </technique>
  121.               </extra>
  122.             </node>
  123.             <node name="pSphere1_ncl1_1" id="pSphere1_ncl1_1" sid="pSphere1_ncl1_1">
  124.               <matrix sid="matrix">1.000000 0.000000 0.000000 -7.182602 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 9.450900 0.000000 0.000000 0.000000 1.000000</matrix>
  125.               <instance_geometry url="#pSphere1_ncl1_1-lib">
  126.                 <bind_material>
  127.                   <technique_common>
  128.                     <instance_material symbol="lambert2" target="#lambert2"/>
  129.                   </technique_common>
  130.                 </bind_material>
  131.               </instance_geometry>
  132.               <extra>
  133.                 <technique profile="FCOLLADA">
  134.                   <visibility>1.000000</visibility>
  135.                 </technique>
  136.               </extra>
  137.             </node>
  138.           </node>
  139.           <node name="grp_cilindros01_ncl1_1" id="grp_cilindros01_ncl1_1" sid="grp_cilindros01_ncl1_1">
  140.             <matrix sid="matrix">1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</matrix>
  141.             <extra>
  142.               <technique profile="FCOLLADA">
  143.                 <visibility>1.000000</visibility>
  144.               </technique>
  145.             </extra>
  146.             <node name="pCylinder1_ncl1_1" id="pCylinder1_ncl1_1" sid="pCylinder1_ncl1_1">
  147.               <matrix sid="matrix">1.000000 0.000000 0.000000 36.367127 0.000000 1.000000 0.000000 15.203651 0.000000 0.000000 1.000000 -34.329298 0.000000 0.000000 0.000000 1.000000</matrix>
  148.               <instance_geometry url="#pCylinder1_ncl1_1-lib">
  149.                 <bind_material>
  150.                   <technique_common>
  151.                     <instance_material symbol="lambert2" target="#lambert2"/>
  152.                   </technique_common>
  153.                 </bind_material>
  154.               </instance_geometry>
  155.               <extra>
  156.                 <technique profile="FCOLLADA">
  157.                   <visibility>1.000000</visibility>
  158.                 </technique>
  159.               </extra>
  160.             </node>
  161.             <node name="pCylinder2_ncl1_1" id="pCylinder2_ncl1_1" sid="pCylinder2_ncl1_1">
  162.               <matrix sid="matrix">1.000000 0.000000 0.000000 64.502382 0.000000 1.000000 0.000000 13.311090 0.000000 0.000000 1.000000 -42.815139 0.000000 0.000000 0.000000 1.000000</matrix>
  163.               <instance_geometry url="#pCylinder2_ncl1_1-lib">
  164.                 <bind_material>
  165.                   <technique_common>
  166.                     <instance_material symbol="lambert2" target="#lambert2"/>
  167.                   </technique_common>
  168.                 </bind_material>
  169.               </instance_geometry>
  170.               <extra>
  171.                 <technique profile="FCOLLADA">
  172.                   <visibility>1.000000</visibility>
  173.                 </technique>
  174.               </extra>
  175.             </node>
  176.           </node>
  177.         </node>
  178.       </node>
  179.       <extra>
  180.         <technique profile="MAX3D">
  181.           <frame_rate>24.000000</frame_rate>
  182.         </technique>
  183.         <technique profile="FCOLLADA">
  184.           <start_time>0.041667</start_time>
  185.           <end_time>2.000000</end_time>
  186.         </technique>
  187.       </extra>
  188.     </visual_scene>
  189.   </library_visual_scenes>
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2013-01-18 19:45 @864, editado 2 veces en total
Razón: Poner marcas XML al código XML...
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Re: Procesar archivo XML gigantesco en Perl

Notapor explorer » 2013-01-18 19:20 @847

XML::Simple no es capaz de leer archivos tan grandes. O sí es capaz pero tarda muchísimo, o se agota la memoria.

Hay otras técnicas para leer XML grandes, como las que se comentan en este artículo, pero el problema lo tienes entonces en querer almacenar la estructura en memoria. Si con XML::Simple no entraba, menos lo hará con otros módulos: sencillamente, no entra. Pero si de todo el archivo solo estás interesado en ciertos nodos, XML::Parse::PerlSAX (y muchos otros) te pueden servir, ya que dispararán eventos cuando encuentren las marcas de apertura y cierre de las etiquetas, y si se trata de una etiqueta que nos interesa podemos capturar su interior.

Es más: el propio XML::Simple puede trabajar de esa manera. En las últimas versiones puede hacer uso de la biblioteca SAX2, para recrear la estructura que un filtro haya extraído del XML con la ayuda de SAX2 (ver sección SAX SUPPORT en el manual de XML::Simple).

Otra opción sería hacer varias pasadas. La primera extraería las líneas que sólo nos interesan. De allí le agregamos unas marcas XML falsas al principio y al final, y ya se lo podemos pasar a XML::Simple (si aún cabe todo en memoria, claro).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesar archivo XML gigantesco en Perl

Notapor danimera » 2013-01-19 08:33 @398

Sí señor, lo que tu me dices está bien...

Cuando yo filtro el archivo son unas seiscientas mil líneas de XML que es donde está la información...

Quería pasarlo a memoria porque, como entiendo, son nodos de una estructura de árbol, eso yo no lo entiendo bien...

Usaré esa forma; filtraré y se lo pasaré al XML::Simple para ver si aún cabe en memoria...

Gracias
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados