正在将 XML 个文件解析为 CSV - NameError
Parsing XML files to CSV - NameError
我正在为特定元素和属性解析包含数千 XML 文件的大型项目。我已经设法打印了我想要的所有元素和属性,但我无法将它们写入 CSV Table。如果我能在各自的 headers 下得到每个 Element/Attribute 的每一次出现,那就太好了。问题是我收到“NameError: name 'X' is not defined”,我不知道如何重组,在我将变量移至 CSV 之前一切似乎都可以正常工作。
from logging import root
import xml.etree.ElementTree as ET
import csv
import os
path = r'C:\Users\briefe\V'
f = open('jp-elements.csv', 'w', encoding="utf-8")
writer = csv.writer(f)
writer.writerow(["Note", "Supplied", "@Certainty", "@Source"])
#opening files in folder for project
for filename in os.listdir(path):
if filename.endswith(".xml"):
fullpath = os.path.join(path, filename)
#getting the root of each file as my starting point
for file in fullpath:
tree = ET.parse(fullpath)
root = tree.getroot()
try:
for note in root.findall('.//note'):
notes = note.attrib, note.text
for supplied in root.findall(".//supplied"):
print(supplied.attrib)
for suppliedChild in supplied.findall(".//*"):
supplies = suppliedChild.tag, suppliedChild.attrib
#attribute search
for responsibility in root.findall(".//*[@resp]"):
responsibilities = responsibility.tag, responsibility.attrib, responsibility.text
for certainty in root.findall(".//*[@cert]"):
certainties = certainty.tag, certainty.attrib, certainty.text
writer.writerow([notes, supplies, responsibilities, certainties])
finally:
f.close()
如您所愿,我正在尝试保存如下所示的结果:
{http://www.tei-c.org/ns/1.0}add {'resp': '#MB', 'status': 'unremarkable'} Nach H gedruckt IV. Abt., V, Anhang Nr.
10.
{http://www.tei-c.org/ns/1.0}date {'cert': 'medium', 'when': '1805-04-09'} 9. April 1805
我正在尝试将这些元组和字典项的混合作为字符串保存到 csv 字段中。但是我得到“NameError:name 'notes' is not defined”,例如。
XML 代码示例:
<?xml version="1.0" encoding="UTF-8"?><TEI xmlns="http://www.tei-c.org/ns/1.0" type="letter" xml:id="V_100">
<teiHeader>
</teiHeader>
<text>
<body>
<div type="letter">
<note type="ig">Kopie</note>
<p>Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick<lb xml:id="V_39-7" rendition="#hyphen"/>steinchen einzuschieben. Philemon und Baucis müssen —
wenn<note corresp="#V_39-8">
<listPerson type="lineReference">
<person corresp="#JP-000228">
<persName>
<name cert="high" type="reg">Baucis</name>
</persName>
</person>
<person corresp="#JP-003214" ana="†">
<persName>
<name cert="low" type="reg">Philemon</name>
</persName>
</person>
</listPerson>
<p>
<hi rendition="#aq">Der Brief ist vielleicht nicht an den Minister Hardenberg
gerichtet,<lb/>
</p>
<lb/>
</div>
</body>
</text>
</TEI>
正如所发布的那样,XML 在根目录下有一个默认的命名空间,必须考虑 每个 元素的命名引用,例如 <note>
。因此,请考虑此调整,其中 notes
将被正确分配。
nsmp = "http://www.tei-c.org/ns/1.0"
for note in root.findall(f'.//{{{nsmp}}}note'):
notes = note.attrib, note.text
三重大括号是为了确保内插字符串值包含在大括号中,这也是 F 字符串中使用的符号。请注意,您的代码也会因未找到 supplies
而出错。
但是,根据您的意见,考虑一个动态解决方案,它不对任何元素名称进行硬编码,而是解析所有元素和属性并将输出扁平化为 CSV 格式。下面使用嵌套的 list/dict 理解来解析 XML 数据并使用 csv.DictWriter
迁移到 CSV,后者将字典映射到 CSV 的字段名称。此外,下面使用上下文管理器 with()
来写入文本并且不需要 close()
命令。
with open('Output.csv', 'w', newline='') as f:
writer = csv.DictWriter(
f, fieldnames=['element_or_attribute', 'text_or_value']
)
# MERGES DICTIONARIES OF ELEMENTS AND ATTRIBUTES
# DICT KEYS REMOVE NAMESPACES AND CHECKS FOR NoneTypes
# ATTRIBUTES ARE PREFIXED WITH PARENT ELEMENT NAME
xml_dicts = [{
**{el.tag.split('}')[1]:(
el.text.strip() if el.text is not None else el.text
)},
**{(
el.tag.split('}')[1]+'_'+k.split('}')[1]
if '}' in k
else el.tag.split('}')[1]+'_'+k):v
for k,v in el.attrib.items()}
} for i, el in enumerate(root.findall(f'.//*'), start=1)]
# COMBINES ABOVE DICTS INTO FLATTER FORMAT
csv_dicts = [
{'element_or_attribute': k, 'text_or_value':v}
for d in xml_dicts
for k, v in d.items()
]
writer.writeheader()
writer.writerows(csv_dicts)
上面的内容应该集成到你的文件循环中,在这里处理 one XML 文件到 one CSV。
CSV 输出
element_or_attribute
text_or_value
teiHeader
text
body
div
div_type
letter
note
Kopie
note_type
ig
p
"Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick"
lb
lb_id
V_39-7
lb_rendition
#hyphen
note
note_corresp
#V_39-8
listPerson
listPerson_type
lineReference
person
person_corresp
#JP-000228
persName
name
Baucis
name_cert
high
name_type
reg
person
person_corresp
#JP-003214
person_ana
†
persName
name
Philemon
name_cert
low
name_type
reg
p
hi
"Der Brief ist vielleicht nicht an den Minister Hardenberg\n gerichtet,"
hi_rendition
#aq
lb
lb
XML 输入 (针对再现性进行了校正)
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" type="letter" xml:id="V_100">
<teiHeader></teiHeader>
<text>
<body>
<div type="letter">
<note type="ig">Kopie</note>
<p>Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick<lb xml:id="V_39-7" rendition="#hyphen"/>steinchen einzuschieben. Philemon und Baucis müssen —
wenn<note corresp="#V_39-8"/>
<listPerson type="lineReference">
<person corresp="#JP-000228">
<persName>
<name cert="high" type="reg">Baucis</name>
</persName>
</person>
<person corresp="#JP-003214" ana="†">
<persName>
<name cert="low" type="reg">Philemon</name>
</persName>
</person>
</listPerson>
</p>
<p>
<hi rendition="#aq">Der Brief ist vielleicht nicht an den Minister Hardenberg
gerichtet,<lb/></hi>
</p>
<lb/>
</div>
</body>
</text>
</TEI>
我正在为特定元素和属性解析包含数千 XML 文件的大型项目。我已经设法打印了我想要的所有元素和属性,但我无法将它们写入 CSV Table。如果我能在各自的 headers 下得到每个 Element/Attribute 的每一次出现,那就太好了。问题是我收到“NameError: name 'X' is not defined”,我不知道如何重组,在我将变量移至 CSV 之前一切似乎都可以正常工作。
from logging import root
import xml.etree.ElementTree as ET
import csv
import os
path = r'C:\Users\briefe\V'
f = open('jp-elements.csv', 'w', encoding="utf-8")
writer = csv.writer(f)
writer.writerow(["Note", "Supplied", "@Certainty", "@Source"])
#opening files in folder for project
for filename in os.listdir(path):
if filename.endswith(".xml"):
fullpath = os.path.join(path, filename)
#getting the root of each file as my starting point
for file in fullpath:
tree = ET.parse(fullpath)
root = tree.getroot()
try:
for note in root.findall('.//note'):
notes = note.attrib, note.text
for supplied in root.findall(".//supplied"):
print(supplied.attrib)
for suppliedChild in supplied.findall(".//*"):
supplies = suppliedChild.tag, suppliedChild.attrib
#attribute search
for responsibility in root.findall(".//*[@resp]"):
responsibilities = responsibility.tag, responsibility.attrib, responsibility.text
for certainty in root.findall(".//*[@cert]"):
certainties = certainty.tag, certainty.attrib, certainty.text
writer.writerow([notes, supplies, responsibilities, certainties])
finally:
f.close()
如您所愿,我正在尝试保存如下所示的结果:
{http://www.tei-c.org/ns/1.0}add {'resp': '#MB', 'status': 'unremarkable'} Nach H gedruckt IV. Abt., V, Anhang Nr.
10.
{http://www.tei-c.org/ns/1.0}date {'cert': 'medium', 'when': '1805-04-09'} 9. April 1805
我正在尝试将这些元组和字典项的混合作为字符串保存到 csv 字段中。但是我得到“NameError:name 'notes' is not defined”,例如。
XML 代码示例:
<?xml version="1.0" encoding="UTF-8"?><TEI xmlns="http://www.tei-c.org/ns/1.0" type="letter" xml:id="V_100">
<teiHeader>
</teiHeader>
<text>
<body>
<div type="letter">
<note type="ig">Kopie</note>
<p>Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick<lb xml:id="V_39-7" rendition="#hyphen"/>steinchen einzuschieben. Philemon und Baucis müssen —
wenn<note corresp="#V_39-8">
<listPerson type="lineReference">
<person corresp="#JP-000228">
<persName>
<name cert="high" type="reg">Baucis</name>
</persName>
</person>
<person corresp="#JP-003214" ana="†">
<persName>
<name cert="low" type="reg">Philemon</name>
</persName>
</person>
</listPerson>
<p>
<hi rendition="#aq">Der Brief ist vielleicht nicht an den Minister Hardenberg
gerichtet,<lb/>
</p>
<lb/>
</div>
</body>
</text>
</TEI>
正如所发布的那样,XML 在根目录下有一个默认的命名空间,必须考虑 每个 元素的命名引用,例如 <note>
。因此,请考虑此调整,其中 notes
将被正确分配。
nsmp = "http://www.tei-c.org/ns/1.0"
for note in root.findall(f'.//{{{nsmp}}}note'):
notes = note.attrib, note.text
三重大括号是为了确保内插字符串值包含在大括号中,这也是 F 字符串中使用的符号。请注意,您的代码也会因未找到 supplies
而出错。
但是,根据您的意见,考虑一个动态解决方案,它不对任何元素名称进行硬编码,而是解析所有元素和属性并将输出扁平化为 CSV 格式。下面使用嵌套的 list/dict 理解来解析 XML 数据并使用 csv.DictWriter
迁移到 CSV,后者将字典映射到 CSV 的字段名称。此外,下面使用上下文管理器 with()
来写入文本并且不需要 close()
命令。
with open('Output.csv', 'w', newline='') as f:
writer = csv.DictWriter(
f, fieldnames=['element_or_attribute', 'text_or_value']
)
# MERGES DICTIONARIES OF ELEMENTS AND ATTRIBUTES
# DICT KEYS REMOVE NAMESPACES AND CHECKS FOR NoneTypes
# ATTRIBUTES ARE PREFIXED WITH PARENT ELEMENT NAME
xml_dicts = [{
**{el.tag.split('}')[1]:(
el.text.strip() if el.text is not None else el.text
)},
**{(
el.tag.split('}')[1]+'_'+k.split('}')[1]
if '}' in k
else el.tag.split('}')[1]+'_'+k):v
for k,v in el.attrib.items()}
} for i, el in enumerate(root.findall(f'.//*'), start=1)]
# COMBINES ABOVE DICTS INTO FLATTER FORMAT
csv_dicts = [
{'element_or_attribute': k, 'text_or_value':v}
for d in xml_dicts
for k, v in d.items()
]
writer.writeheader()
writer.writerows(csv_dicts)
上面的内容应该集成到你的文件循环中,在这里处理 one XML 文件到 one CSV。
CSV 输出
element_or_attribute | text_or_value |
---|---|
teiHeader | |
text | |
body | |
div | |
div_type | letter |
note | Kopie |
note_type | ig |
p | "Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick" |
lb | |
lb_id | V_39-7 |
lb_rendition | #hyphen |
note | |
note_corresp | #V_39-8 |
listPerson | |
listPerson_type | lineReference |
person | |
person_corresp | #JP-000228 |
persName | |
name | Baucis |
name_cert | high |
name_type | reg |
person | |
person_corresp | #JP-003214 |
person_ana | † |
persName | |
name | Philemon |
name_cert | low |
name_type | reg |
p | |
hi | "Der Brief ist vielleicht nicht an den Minister Hardenberg\n gerichtet," |
hi_rendition | #aq |
lb | |
lb |
XML 输入 (针对再现性进行了校正)
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" type="letter" xml:id="V_100">
<teiHeader></teiHeader>
<text>
<body>
<div type="letter">
<note type="ig">Kopie</note>
<p>Erlauben Sie mir, in Ihre Ehrenpforte noch einige Zwick<lb xml:id="V_39-7" rendition="#hyphen"/>steinchen einzuschieben. Philemon und Baucis müssen —
wenn<note corresp="#V_39-8"/>
<listPerson type="lineReference">
<person corresp="#JP-000228">
<persName>
<name cert="high" type="reg">Baucis</name>
</persName>
</person>
<person corresp="#JP-003214" ana="†">
<persName>
<name cert="low" type="reg">Philemon</name>
</persName>
</person>
</listPerson>
</p>
<p>
<hi rendition="#aq">Der Brief ist vielleicht nicht an den Minister Hardenberg
gerichtet,<lb/></hi>
</p>
<lb/>
</div>
</body>
</text>
</TEI>