1 回答

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超10個(gè)贊
您可以構(gòu)建一個(gè)列表列表來表示表的行。每當(dāng)需要新行時(shí),都會(huì)使用默認(rèn)的所有已知列構(gòu)建一個(gè)新列表"",并將其附加到外部列表的底部。當(dāng)需要插入新列時(shí),只需旋轉(zhuǎn)現(xiàn)有內(nèi)部列表并附加默認(rèn)""單元格即可。保留已知列名稱的映射以在行中建立索引?,F(xiàn)在,當(dāng)您瀏覽事件時(shí),您可以使用標(biāo)記名稱來查找行索引并將其值添加到表中的最新行。
看起來您想要“l(fā)og”和“alarm”標(biāo)簽,但我編寫了元素選擇器來獲取具有“eventType”子元素的任何元素。由于“l(fā)ongName”和“shortName”對于給定的所有事件都是通用的,因此有一個(gè)外部循環(huán)來獲取這些事件并將其應(yīng)用于表的每個(gè)新行。我切換到xpath這樣我就可以設(shè)置命名空間并更簡潔地編寫選擇器。個(gè)人喜好,但我認(rèn)為它使 xpath 更具可讀性。
import csv
import lxml.etree
from lxml.etree import QName
import operator
class ExpandingTable:
"""A 2 dimensional table where columns are exapanded as new column
types are discovered"""
def __init__(self):
"""Create table that can expand rows and columns"""
self.name_to_col = {}
self.table = []
def add_column(self, name):
"""Add column named `name` unless already included"""
if name not in self.name_to_col:
self.name_to_col[name] = len(self.name_to_col)
for row in self.table:
row.append('')
def add_cell(self, name, value):
"""Add value to named column in the current row"""
if value:
self.add_column(name)
self.table[-1][self.name_to_col[name]] = value.strip().replace("\r\n", " ")
def new_row(self):
"""Create a new row and make it current"""
self.table.append([''] * len(self.name_to_col))
def header(self):
"""Gather discovered column names into a header list"""
idx_1 = operator.itemgetter(1)
return [name for name, _ in sorted(self.name_to_col.items(), key=idx_1)]
def prepend_header(self):
"""Gather discovered column names into a header and
prepend it to the list"""
self.table.insert(0, self.header())
def events_to_table(elem):
""" Builds table from <family> child elements and their contained alarms and
logs."""
ns = {"f":"urn:nortel:namespaces:mcp:faults"}
table = ExpandingTable()
for family in elem.xpath("f:family", namespaces=ns):
longName = family.get("longName")
shortName = family.get("shortName")
for event in family.xpath("*/*[f:eventType]", namespaces=ns):
table.new_row()
table.add_cell("longName", longName)
table.add_cell("shortName", shortName)
for cell in event:
tag = QName(cell.tag).localname
if tag == "severities":
tag = "severity"
text = ",".join(severity.text for severity in cell.xpath("*"))
print("severities", repr(text))
else:
text = cell.text
table.add_cell(tag, text)
table.prepend_header()
return table.table
def main(filename):
doc = lxml.etree.parse(filename)
table = events_to_table(doc.getroot())
with open('test.csv', 'w', newline='', encoding='utf-8') as fileobj:
csv.writer(fileobj).writerows(table)
main('test.xml')
添加回答
舉報(bào)