2012-07-20 9 views
6

Hace 2 días Me presentaron por primera vez a Python (y la programación en general). Hoy estoy atascado. He pasado horas tratando de encontrar una respuesta a lo que sospecho que es un problema tan trivial, nadie más ha estado atrapado aquí:)Python: cómo anidar los bucles de lectura de archivos?

El jefe quiere que limpie manualmente ENORME archivos .xml en algo más legible para humanos . Intento crear un guión para hacerlo por mí. El siguiente es un ejemplo del archivo .xml, así como mi resultado deseado.

de entrada (File.xml):

<IssueTracking> 
    <Issue> 
    <SequenceNum>123</SequenceNum> 
    <Subject>Subject of Ticket 123</Subject> 
    <Description>Line 1 in Description field of Ticket 123. 
Line 2 in Description field of Ticket 123. 
Line 3 in Description field of Ticket 123.</Description> 
    </Issue> 
    <Issue> 
    <SequenceNum>124</SequenceNum> 
    <Subject>Subject of Ticket 124</Subject> 
    <Description>Line 1 in Description field of Ticket 124. 
Line 2 in Description field of Ticket 124. 
Line 3 in Description field of Ticket 124.</Description> 
    </Issue> 
</IssueTracking> 

salida deseada:

123 Subject of Ticket 123 
Line 1 in Description field of Ticket 123. 
Line 2 in Description field of Ticket 123. 
Line 3 in Description field of Ticket 123. 

124 Subject of Ticket 124 
Line 1 in Description field of Ticket 124. 
Line 2 in Description field of Ticket 124. 
Line 3 in Description field of Ticket 124. 

Aquí es lo que tengo hasta ahora.

with open(File.xml, 'r') as SourceFile: # Opens the file 
    while 1: # Keep going through the file to the end 
     SourceFileLine = SourceFile.readline() # Saves lines of the source file 
     if not SourceFileLine: # Skip empty lines 
      break 

     SourceFileLine = SourceFileLine.strip() # Strips the whitespace 

     if "<SequenceNum>" in SourceFileLine: 
      SequenceNum = SourceFileLine[13:-14] # Trims the tags, saves the field. 
      continue 

     if "<Subject>" in SourceFileLine: 
      Subject = SourceFileLine[9:-10] 
      continue 

     #if "<Description>" in SourceFileLine: 
     # last_pos = SourceFile.tell() 
     # while "</Description>" not in SourceFileLine: 
     #  SourceFile.seek(last_pos) 
     #  ????? 
     #  
     # Description = Description[22:] 
     # continue 

     if "</Issue>" in SourceFileLine: 
      print(SequenceNum, end = "\t") 
      print(Subject) 
     # print(Description) 
      print("\n") 

estoy atascado en la identificación y retención de esas tres líneas entre los <Description> etiquetas en una sola cadena que puedo imprimir antes de continuar por el archivo de origen. Ahora que he escaneado docenas de otros ejemplos de bucles de lectura de líneas de archivos, sospecho que lo que necesito es señalar el punto en el que llego al campo de destino y anidar otro ciclo de lectura en ese punto del archivo. Pero no he encontrado otro ejemplo de esto, así que asumo que me falta algo básico o que hay una mejor manera. ¡Gracias de antemano por la ayuda!

+1

Python tiene incorporado un analizador XML: http://docs.python.org /library/pyexpat.html –

+3

+1 para la entrada, el resultado deseado y lo que ha intentado. –

+0

Probablemente deberías utilizar un serializador amigable para el ser humano como YAML para enviar los datos una vez que los hayas extraído. Nunca se sabe cuándo tendrá que procesar esta información nuevamente. –

Respuesta

7

Un ejemplo del uso lxml que recomiendo encarecidamente para procesar sus datos. (NB: escrito para Py2.x pero fácil de adaptar a Py3.x)

from lxml import etree 
xml = """<IssueTracking> 
    <Issue> 
    <SequenceNum>123</SequenceNum> 
    <Subject>Subject of Ticket 123</Subject> 
    <Description>Line 1 in Description field of Ticket 123. 
Line 2 in Description field of Ticket 123. 
Line 3 in Description field of Ticket 123.</Description> 
    </Issue> 
    <Issue> 
    <SequenceNum>124</SequenceNum> 
    <Subject>Subject of Ticket 124</Subject> 
    <Description>Line 1 in Description field of Ticket 124. 
Line 2 in Description field of Ticket 124. 
Line 3 in Description field of Ticket 124.</Description> 
    </Issue> 
</IssueTracking> 
""" 

root = etree.fromstring(xml) 
for issue in root.findall('Issue'): 
    as_list = [issue.find(n).text for n in ('SequenceNum', 'Subject', 'Description')] 
    as_list[2] = as_list[2].split('\n') 
    print as_list 

Lienzo:

['123', 'Subject of Ticket 123', ['Line 1 in Description field of Ticket 123.', 'Line 2 in Description field of Ticket 123.', 'Line 3 in Description field of Ticket 123.']] 
['124', 'Subject of Ticket 124', ['Line 1 in Description field of Ticket 124.', 'Line 2 in Description field of Ticket 124.', 'Line 3 in Description field of Ticket 124.']] 
6

Por favor, no lea archivos XML como este, para Python hay varias bibliotecas que ayudarán en la lectura de archivos XML.

Mire la biblioteca python lxml que proporciona una manera muy fácil de leer y analizar archivos XML y mejorará enormemente su código.

me explico cómo utilizar la biblioteca en sí, sino su documentación es mucho mejor de lo que puede caber en esta área de texto: http://lxml.de/tutorial.html

+0

Gracias, estudiaré esto y lo resolveré. Aprecio tu ayuda. – phlogiston