亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將 XML 文件解析為 CSV,無需硬編碼值

將 XML 文件解析為 CSV,無需硬編碼值

慕的地8271018 2023-10-31 14:29:16
我想知道是否有一種方法可以解析 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>
查看完整描述

1 回答

?
白衣染霜花

TA貢獻1796條經驗 獲得超10個贊

您可以構建一個列表列表來表示表的行。每當需要新行時,都會使用默認的所有已知列構建一個新列表"",并將其附加到外部列表的底部。當需要插入新列時,只需旋轉現有內部列表并附加默認""單元格即可。保留已知列名稱的映射以在行中建立索引。現在,當您瀏覽事件時,您可以使用標記名稱來查找行索引并將其值添加到表中的最新行。


看起來您想要“log”和“alarm”標簽,但我編寫了元素選擇器來獲取具有“eventType”子元素的任何元素。由于“longName”和“shortName”對于給定的所有事件都是通用的,因此有一個外部循環來獲取這些事件并將其應用于表的每個新行。我切換到xpath這樣我就可以設置命名空間并更簡潔地編寫選擇器。個人喜好,但我認為它使 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')


查看完整回答
反對 回復 2023-10-31
  • 1 回答
  • 0 關注
  • 116 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號