У меня есть много файлов XML, которые выглядят так
<?xml version = "1.0" encoding = "utf-8" standalone = "no"?>
<reiXmlPrenos>
<Qfl>1808</Qfl>
<fOVE>13.7</fOVE>
<NetoVolumen>613</NetoVolumen>
<Hv>104.2</Hv>
<energenti>
<energent>
<sifra>energy_e</sifra>
<naziv>EE [kWh]</naziv>
<vrednost>238981</vrednost>
</energent>
<energent>
<sifra>energy_to</sifra>
<naziv>Do</naziv>
<vrednost>16359</vrednost>
</energent>
<energent>
<sifra>energy_en</sifra>
<naziv>En</naziv>
<vrednost>0</vrednost>
</energent>
</energenti>
<rei>
<zavetrovanost>2</zavetrovanost>
<cone>
<cona>
<cona_id>1</cona_id>
<cc_si_cona>1110000</cc_si_cona>
<visina_cone>2.7</visina_cone>
<dolzina_cone>14</dolzina_cone>
</cona>
<cona>
<cona_id>2</cona_id>
<cc_si_cona>120000</cc_si_cona>
</cona>
</rei>
</reiXmlPrenos>
Я хотел бы извлечь определенные значения из этих файлов XML. Итак, я собрал с помощью людей приведенный ниже код, который должен работать:
import pandas as pd
import glob
import os
from lxml import etree
os.chdir(r'R:\...\XML-1122_test')
dir_path = glob.glob('*.xml')
xmls = dir_path
#note: For simplicity, I'm using the well formed version of the xml strings in your question; you'll have to use actual file names and paths
energies = ["xml", "energy_ge", "energy_en", "energy_dteu", "energy_dtlb"]
#I just made up some names - you'll have to use actual names, of course; the first one is for the file identifier - see below
rows = []
for xml in xmls:
row = []
id = "xml-"+str(xmls.index(xml)+1)
#this creates the file identifier
row.append(id)
root = etree.XML(xml.encode())
#in real life, you'll have to use the parse() method
for energy in energies[1:]:
#the '[1:]' is used to skip the first "energy"; it's only used as the file identifier
target = root.xpath(f'//energent[./sifra[. = "{energy}"]]/vrednost/text()')
#note the use of f-strings
row.extend( target if len(target)>0 else "0" )
rows.append(row)
print(pd.DataFrame(rows,columns=energies))
Но в итоге получаю предупреждение:
File "<string>", line 1
XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1
Это проблема XML? Или, может быть, проблема с lxml? Кто-нибудь знает, как к этому подойти?
В идеале результат должен выглядеть так
xml energy_e energy_en energy_to
xml-1 238981 0 16539
xml-2 ... .. ..
@energyMax, можете ли вы добавить точный ожидаемый фрейм данных (соответствующий вашему вводу)?
Вы используете etree.XML(xml.encode()) вместо парсера? xmls это пути к файлам, а не содержимое xml
Весь код представлен выше.
Тогда может в этом проблема. Вы должны использовать parse().






import pandas as pd
import glob
import os
from lxml import etree
os.chdir(r'R:\...\XML-1122_test')
dir_path = glob.glob('*.xml')
xmls = dir_path
energies = ["xml", "energy_e", "energy_en", "energy_to"]
rows = []
for xml in xmls:
row = []
id = "xml-"+str(xmls.index(xml)+1)
row.append(id)
with open(xml, 'r', encoding='utf-8') as f:
xml_string = f.read()
root = etree.XML(xml_string.encode())
for energy in energies[1:]:
target = root.xpath(f'//energent[./sifra = "{energy}"]/vrednost/text()')
row.extend(target if len(target)>0 else ["0"])
rows.append(row)
print(pd.DataFrame(rows, columns=energies)
разобрать ниже
import pandas as pd
import glob
import os
from lxml import etree
os.chdir(r'R:\...\XML-1122_test')
dir_path = glob.glob('*.xml')
xmls = dir_path
energies = ["xml", "energy_ge", "energy_en", "energy_dteu", "energy_dtlb"]
rows = []
for xml in xmls:
row = []
id = "xml-"+str(xmls.index(xml)+1)
row.append(id)
root = etree.parse(xml)
for energy in energies[1:]:
target = root.xpath(f'//energent[./sifra[. = "{energy}"]]/vrednost/text()')
row.extend( target if len(target)>0 else "0" )
rows.append(row)
print(pd.DataFrame(rows,columns=energies))
Это решит вашу проблему?
Еще нет. Играет ли какую-то роль то, что сначала есть energenti и только потом energent. Так что energenti выше их всех... Я получаю такое же предупреждение даже сейчас
Я отредактировал сообщение, чтобы лучше решить вашу проблему и ответить на ваш новый вопрос. Пожалуйста, скажите мне, решит ли это вашу проблему.
Не могли бы вы дать весь код в виде дырки? Я немного запутался в некоторых частях atm
Хорошо, дайте мне одну минуту, чтобы собрать его.
Я также могу сделать это с помощью синтаксического анализа, поскольку это жизнеспособное решение.
хорошо, вот оба кода
Поскольку вы ищете фрейм данных, вы можете просто использовать read_xml от pandas:
df = (
pd.read_xml(xml, xpath = ".//energent")
.drop("naziv", axis=1)
.set_index("sifra").T
.rename_axis(None, axis=1)
)
И вот как вы можете включить его в свой код:
xmls = glob.glob("*.xml")
list_dfs = []
for idx, xml in enumerate(xmls, start=1):
tmp_df = (
pd.read_xml(xml, xpath = ".//energent")
.drop("naziv", axis=1)
.set_index("sifra").T
.rename_axis(None, axis=1)
)
tmp_df.insert(0, "xml", f"{xml}-{idx}")
list_dfs.append(tmp_df)
df = pd.concat(list_dfs, ignore_index=True)
Тест/выход (x3 тот же xml):
print(df)
xml energy_e energy_to energy_en
0 first.xml-1 238981 16359 0
1 second.xml-2 238981 16359 0
2 third.xml-3 238981 16359 0
Можно пожалуйста весь код? Я (очевидно) не очень хорошо разбираюсь в питоне, поэтому не могу понять всей логики.
Я обновил свой ответ, можете ли вы его проверить?
NameError: name 'StringIO' is not defined это ошибка
Это потому, что я использовал io для чтения xml, я исправил код.
Пространство является результатом моего процесса копирования-вставки. XML-файлы не имеют места в самом начале. И все остальные теги тоже присутствуют, я скопировал только часть файлов, чтобы дать вам представление о том, как это выглядит.