将 XML 文件解析为 CSV,无需硬编码值

我想知道是否有一种方法可以解析 XML 并基本上获取所有标签(或尽可能多)并将它们放入列中而无需硬编码。

例如我的 xml 中的 eventType 标记。我希望它最初创建一个名为“eventType”的列,并将值放在该列下方。它解析的每个“eventType”标签都会将其放入同一列中。

一般来说,我试图让它看起来像这样:

https://i.stack.imgur.com/z0L8z.png

这是 XML 示例:


<?xml version="1.0" encoding="UTF-8"?>


<faults version="1" xmlns="urn:nortel:namespaces:mcp:faults" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:nortel:namespaces:mcp:faults NortelFaultSchema.xsd ">

    <family longName="1OffMsgr" shortName="OOM"/>

    <family longName="ACTAGENT" shortName="ACAT">

        <logs>

           <log>

                <eventType>RES</eventType>

                <number>1</number>

                <severity>INFO</severity>

                <descTemplate>

                     <msg>Accounting is enabled upon this NE.</msg>

               </descTemplate>

               <note>This log is generated when setting a Session Manager's AM from &lt;none&gt; to a valid AM.</note>

               <om>On all instances of this Session Manager, the &lt;NE_Inst&gt;:&lt;AM&gt;:STD:acct OM row in the  StdRecordStream group will appear and start counting the recording units sent to the configured AM.

                   On the configured AM, the &lt;NE_inst&gt;:acct OM rows in RECSTRMCOLL group will appear and start counting the recording units received from this Session Manager's instances.

               </om>

            </log>

           <log>

                <eventType>RES</eventType>

                <number>2</number>

                <severity>ALERT</severity>

                <descTemplate>

                     <msg>Accounting is disabled upon this NE.</msg>

               </descTemplate>


慕的地8271018
浏览 88回答 1
1回答

白衣染霜花

您可以构建一个列表列表来表示表的行。每当需要新行时,都会使用默认的所有已知列构建一个新列表"",并将其附加到外部列表的底部。当需要插入新列时,只需旋转现有内部列表并附加默认""单元格即可。保留已知列名称的映射以在行中建立索引。现在,当您浏览事件时,您可以使用标记名称来查找行索引并将其值添加到表中的最新行。看起来您想要“log”和“alarm”标签,但我编写了元素选择器来获取具有“eventType”子元素的任何元素。由于“longName”和“shortName”对于给定的所有事件都是通用的,因此有一个外部循环来获取这些事件并将其应用于表的每个新行。我切换到xpath这样我就可以设置命名空间并更简洁地编写选择器。个人喜好,但我认为它使 xpath 更具可读性。import csvimport lxml.etreefrom lxml.etree import QNameimport operatorclass ExpandingTable:&nbsp; &nbsp; """A 2 dimensional table where columns are exapanded as new column&nbsp; &nbsp; types are discovered"""&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; """Create table that can expand rows and columns"""&nbsp; &nbsp; &nbsp; &nbsp; self.name_to_col = {}&nbsp; &nbsp; &nbsp; &nbsp; self.table = []&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; def add_column(self, name):&nbsp; &nbsp; &nbsp; &nbsp; """Add column named `name` unless already included"""&nbsp; &nbsp; &nbsp; &nbsp; if name not in self.name_to_col:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.name_to_col[name] = len(self.name_to_col)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for row in self.table:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row.append('')&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; def add_cell(self, name, value):&nbsp; &nbsp; &nbsp; &nbsp; """Add value to named column in the current row"""&nbsp; &nbsp; &nbsp; &nbsp; if value:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.add_column(name)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.table[-1][self.name_to_col[name]] = value.strip().replace("\r\n", " ")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; def new_row(self):&nbsp; &nbsp; &nbsp; &nbsp; """Create a new row and make it current"""&nbsp; &nbsp; &nbsp; &nbsp; self.table.append([''] * len(self.name_to_col))&nbsp; &nbsp; def header(self):&nbsp; &nbsp; &nbsp; &nbsp; """Gather discovered column names into a header list"""&nbsp; &nbsp; &nbsp; &nbsp; idx_1 = operator.itemgetter(1)&nbsp; &nbsp; &nbsp; &nbsp; return [name for name, _ in sorted(self.name_to_col.items(), key=idx_1)]&nbsp; &nbsp; def prepend_header(self):&nbsp; &nbsp; &nbsp; &nbsp; """Gather discovered column names into a header and&nbsp; &nbsp; &nbsp; &nbsp; prepend it to the list"""&nbsp; &nbsp; &nbsp; &nbsp; self.table.insert(0, self.header())def events_to_table(elem):&nbsp; &nbsp; """ Builds table from <family> child elements and their contained alarms and&nbsp; &nbsp; logs."""&nbsp; &nbsp; ns = {"f":"urn:nortel:namespaces:mcp:faults"}&nbsp; &nbsp; table = ExpandingTable()&nbsp; &nbsp; for family in elem.xpath("f:family", namespaces=ns):&nbsp; &nbsp; &nbsp; &nbsp; longName = family.get("longName")&nbsp; &nbsp; &nbsp; &nbsp; shortName = family.get("shortName")&nbsp; &nbsp; &nbsp; &nbsp; for event in family.xpath("*/*[f:eventType]", namespaces=ns):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.new_row()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.add_cell("longName", longName)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.add_cell("shortName", shortName)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for cell in event:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tag = QName(cell.tag).localname&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if tag == "severities":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tag = "severity"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text = ",".join(severity.text for severity in cell.xpath("*"))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("severities", repr(text))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text = cell.text&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.add_cell(tag, text)&nbsp; &nbsp; table.prepend_header()&nbsp; &nbsp; return table.table&nbsp; &nbsp;&nbsp;def main(filename):&nbsp; &nbsp; doc = lxml.etree.parse(filename)&nbsp; &nbsp; table = events_to_table(doc.getroot())&nbsp; &nbsp; with open('test.csv', 'w', newline='', encoding='utf-8') as fileobj:&nbsp; &nbsp; &nbsp; &nbsp; csv.writer(fileobj).writerows(table)main('test.xml')
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python