#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 Я с удовольствием помогу и приму мой ответ.