Обработка XML не работает

#python #xml #csv

#python #xml #csv

Вопрос:

Я пытаюсь извлечь данные из датчика (он взаимодействует со строками типа xml) и преобразовать их в csv. С моим фактическим кодом я уже пишу XML-файлы, но данные поступают в виде отдельных строк (от root до /root ).

Не знаю, является ли это причиной, но я получаю сообщение об ошибке elementtree.parse после элемента document. Все, что я прочитал до сих пор, проблема заключалась в построении xml (более одного корня, без корня и т. Д.), Поэтому я немного не понимаю своего дела.

Зарегистрирован в XML-файле:

 <li820><data><celltemp>5.1120729e1</celltemp><cellpres>9.7705745e1</cellpres><co2>7.7808494e2</co2><co2abs>5.0983281e-2</co2abs><ivolt>1.1380004e1</ivolt><raw>2726238,1977386</raw></data></li820>
<li820><data><celltemp>5.1120729e1</celltemp><cellpres>9.7684698e1</cellpres><co2>7.7823929e2</co2><co2abs>5.0991268e-2</co2abs><ivolt>1.1380004e1</ivolt><raw>2725850,1976922</raw></data></li820>
<li820><data><celltemp>5.1120729e1</celltemp><cellpres>9.7705745e1</cellpres><co2>7.7797288e2</co2><co2abs>5.0977463e-2</co2abs><ivolt>1.1373291e1</ivolt><raw>2726166,1977001</raw></data></li820>
 

Содержимое одной из предыдущих строк (в виде дерева) :

 <li820>
    <data>
        <celltemp>1.9523970e1</celltemp>
        <cellpres>9.8993663e1</cellpres>
        <co2>3.5942180e4</co2>
        <co2abs>4.0364418e-1</co2abs>
        <ivolt>1.1802978e1</ivolt>
        <raw>2789123,1884335</raw>
    </data>
</li820>
 

Ошибка :

 Traceback (most recent call last):
 File "licor_read.py", line 96, in <module>
  tree = et.parse(file_xml)              # Set XML Parser
 File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1182, in parse
  tree.parse(source, parser)
 File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 656, in parse
  parser.feed(data)
 File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1642, in feed
  self._raiseerror(v)
 File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror
  raise err
xml.etree.ElementTree.ParseError: junk after document element: line 2, column 0
 

Мой код :

 import os, sys, subprocess
import time, datetime
import serial
import string
import glob
import csv
import xml.etree.ElementTree  as et

from xml.etree.ElementTree import XMLParser, XML, fromstring, tostring
from os  import path
from bs4 import BeautifulSoup as bs


#-------------------------------------------------------------
#------------------ Open configurations ----------------------
#-------------------------------------------------------------

  ############
  # Settings #
  ############

DEBUG   = True
LOG     = True
FREQ    = 1
PORT    = '/dev/ttyUSB0'
BAUD    = 9600
PARITY  = 'N'
STOPBIT = 1
BYTE_SZ = 8
TIMEOUT = 5.0

log_dir   = 'logs/'
out_dir   = 'export/'
fname_xml = 'licor820-data-{}.xml'.format(datetime.datetime.now())            # DO NOT touch the {} brackets
fname_csv = 'licor820-data-{}.csv'.format(datetime.datetime.now())            #
isLooping = 20                                                                # Nr of data extractions
isHeader  = True                                                              # Do not touch if data headers are required
isBegin   = False


#-------------------------------------------------------------
#----- Better know what you are doing from this point --------
#-------------------------------------------------------------

  ##################
  # Initialisation #
  ##################

file_xml = os.path.join(log_dir, fname_xml)                                   # Define path and file name
file_csv = os.path.join(out_dir, fname_csv)                                   #
fp_xml   = open(file_xml, 'w')                                                # Open writing streams
fp_csv   = open(file_csv, 'w')                                                #

try:
  buff = serial.Serial(PORT, BAUD, BYTE_SZ, PARITY, STOPBIT, TIMEOUT)         # Open Serial connection
except Exception as e:
  if DEBUG:
    print ("ERROR: {}".format(e))

  sys.exit("Could not connect to the Licor")

csv_writer    = csv.writer(fp_csv)                                            # Define CSV writer
instruct_head = []                                                            # '' 


  ################
  # Main program #
  ################

while isLooping :                                                             # Define nr of refreshed data extracted
  #os.system('clear')
  print('RAW/XML in progress... '   str(isLooping))                           # Debug this loop

  if(isBegin is False) :                                                      # Verify presence of the <licor> tag
    while(buff.readline()[0] is not '<' and buff.readline()[1] is not 'l') :    
      raw_output = buff.readline()                                            # Jump the lines readed until <licor>
  isBegin = True

  raw_output = buff.readline()
  xml_output = raw_output

  print(xml_output)
  fp_xml.write(xml_output)                                                    # Write from serial port to xml 

  isLooping -= 1

fp_xml.close()

tree = et.parse(file_xml)                                                     # Set XML Parser
root = tree.getroot()                                                         # ''

for instruct_row in root.findall('li820'):                                    # XML to CSV buffer
  instruct = []

  if isHeader is True:                                                        # Buffering header
    celltemp = instruct_row.find('celltemp').tag
    instruct_head.append(celltemp)
    cellpres = instruct_row.find('cellpres').tag
    instruct_head.append(cellpres)      
    co2 = instruct_row.find('co2').tag
    instruct_head.append(co2)      
    co2abs = instruct_row.find('co2abs').tag
    instruct_head.append(co2abs)      
    ivolt = instruct_row.find('ivolt').tag
    instruct_head.append(ivolt)      
    raw = instruct_row.find('raw').tag
    instruct_head.append(raw)

    csv_writer.writerow(instruct_head)                                        # Write header      
    isHeader = False

  celltemp = instruct_row.find('celltemp').text                               # Buffering data
  instruct.append(celltemp)    
  cellpres = instruct_row.find('cellpres').text
  instruct.append(cellpres)    
  co2 = instruct_row.find('co2').text
  instruct.append(co2)    
  co2abs = instruct_row.find('co2abs').text
  instruct.append(co2abs)      
  ivolt = instruct_row.find('ivolt').text
  instruct.append(ivolt)      
  raw = instruct_row.find('raw').text
  instruct.append(raw)

  csv_writer.writerow(instruct)                                             # Write data'''

csv_writer.close()
fp_csv.close()
os.system('clear')

print('Job done. nSaved at : ./'   file_xml   'nAnd at ./'   file_csv   'n')
 

Комментарии:

1. Это первый фрагмент вашего ввода XML? Это неправильно сформированный XML, поскольку в нем отсутствует корневой элемент, содержащий все остальные элементы, поэтому я думаю, что именно это вызывает сообщение об ошибке.

2. корень <li820> каждая строка представляет собой полное дерево

3. Как упоминает @MartinHonnen, ваш XML должен заключать все строки в корневой элемент, чтобы быть правильно сформированным, а не только отдельные строки : <root>...content...</root> . Таким образом, каждый <li820> из них является дочерним для root.

4. действительно, это сработало после изменения моей структуры xml, спасибо вам всем

Ответ №1:

Вы должны открыть свой входной файл с помощью ‘read’ вместо ‘write’. Или вы очистите свой файл при запуске своего кода.

 fp_xml   = open(file_xml, 'r');
 

Кроме того, у меня есть лучший способ получить все элементы.Вам не нужно заранее знать имена всех тегов.

 header = []
isHeader = True
for instruct_row in root.getchildren():  # XML to CSV buffer
    instruct = []

    for i,item in enumerate(instruct_row.getchildren()):
        if isHeader is True:
            header.append(item.tag)
        instruct.append(item.text)
    isHeader = False
    csv_writer.writerow(instruct)# Write data'''
fp_csv.close()
 

Мой входной xml приведен ниже:

 <li820>
<data><celltemp>5.1120729e1</celltemp><cellpres>9.7705745e1</cellpres><co2>7.7808494e2</co2><co2abs>5.0983281e-2</co2abs><ivolt>1.1380004e1</ivolt><raw>2726238,1977386</raw></data>
<data><celltemp>5.1120729e1</celltemp><cellpres>9.7705745e1</cellpres><co2>7.7808494e2</co2><co2abs>5.0983281e-2</co2abs><ivolt>1.1380004e1</ivolt><raw>2726238,1977386</raw></data>
</li820>
 

Наконец, вы можете увидеть данные в своем CSV-файле.

Комментарии:

1. замечательно, попробовал сегодня утром на работе, он отлично справился с задачей.

2. @LaurentFournier Я с удовольствием помогу и приму мой ответ.