【问题标题】:Parsing an XML file to convert to a CSV解析 XML 文件以转换为 CSV
【发布时间】:2021-01-09 20:41:50
【问题描述】:

我无法正确解析 xml 文件中的元素(请参阅下面的 xml sn-p)并将它们转换为 csv。

csv 文件包含 eventType、probableCause、alarmName、shortName (ACAT, AC etc) 和 longName (ACTangent, ACODE, etc) 的列

类似的想法:

目前,我只能让它从警报开始解析信息,但我希望它从一开始就开始。如何为每个日志和警报提取一列中的系列 longName 和另一列中的系列短名称?

如果需要任何澄清,请告诉我。

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>
               <note>This log is generated when setting a Session Manager's AM from a valid AM to &lt;none&gt;.</note>
               <action>If you do not intend for the Session Manager to produce accounting records, then no action is required.  If you do intend for the Session Manager to produce accounting records, then you should set the Session Manager's AM to a valid AM.</action>
               <om>On all instances of this Session Manager, the &lt;NE_Inst&gt;:&lt;AM&gt;:STD:acct OM row in the StdRecordStream group that matched the previous datafilled AM will disappear.
                   On the previously configured AM, the  &lt;NE_inst&gt;:acct OM rows in RECSTRMCOLL group will disappear.
               </om>
            </log>
        </logs>
    </family>
    <family longName="ACODE" shortName="AC">
        <alarms>
            <alarm>
                <eventType>ADMIN</eventType>
                <number>1</number>
                <probableCause>INFORMATION_MODIFICATION_DETECTED</probableCause>
                <descTemplate>
                    <msg>Configured data for audiocode server updated: $1</msg>
                     <param>
                         <num>1</num>
                         <description>AudioCode configuration data got updated</description>
                         <exampleValue>acgwy1</exampleValue>
                     </param>
               </descTemplate>
               <manualClearable></manualClearable>
               <correctiveAction>None. Acknowledge/Clear alarm and deploy the audiocode server if appropriate.</correctiveAction>
               <alarmName>Audiocode Server Updated</alarmName>
               <severities>
                     <severity>MINOR</severity>
               </severities>               
            </alarm>
            <alarm>
                <eventType>ADMIN</eventType>
                <number>2</number>
                <probableCause>CONFIG_OR_CUSTOMIZATION_ERROR</probableCause>
                <descTemplate>
                    <msg>Deployment for audiocode server failed: $1. Reason: $2.</msg>
                     <param>
                         <num>1</num>
                         <description>AudioCode Name</description>
                         <exampleValue>audcod</exampleValue>
                     </param>
                     <param>
                         <num>2</num>
                         <description>AudioCode Deployment failed reason</description>
                         <exampleValue>Failed to parse audiocode configuration data</exampleValue>
                     </param>
               </descTemplate>
               <manualClearable></manualClearable>
               <correctiveAction>Check the configuration of audiocode server. Acknowledge/Clear alarm and deploy the audiocode server if appropriate.</correctiveAction>
               <alarmName>Audiocode Server Deploy Failed</alarmName>
               <severities>
                     <severity>MINOR</severity> 
               </severities>               
            </alarm>
        </alarms>
    </family>
</faults>

我的代码

from xml.etree import ElementTree
import csv


tree = ElementTree.parse('Fault.xml')

sitescope_data = open('Out.csv', 'w', newline='', encoding='utf-8')
csvwriter = csv.writer(sitescope_data)

#Create all needed columns here in order and writes them to excel file
col_names = ['eventType', 'probableCause', 'severity', 'alarmName', 'shortName', 'longName']
csvwriter.writerow(col_names)

def recurse(root):
    for child in root:
        recurse(child)
        print(child.tag)

    for  event in root.findall('{urn:nortel:namespaces:mcp:faults}alarm'):
        event_data = []
        event_id = event.find('{urn:nortel:namespaces:mcp:faults}eventType')
        if event_id != None:
            event_id = event_id.text
        event_data.append(event_id)

        probableCause = event.find('{urn:nortel:namespaces:mcp:faults}probableCause')
        if probableCause != None:
            probableCause = probableCause.text
        event_data.append(probableCause)

        severities = event.find('{urn:nortel:namespaces:mcp:faults}severities')
        if severities:
            severity_data = ','.join(
                [sv.text for sv in severities.findall('{urn:nortel:namespaces:mcp:faults}severity')])
            event_data.append(severity_data)
        else:
            event_data.append("")

        alarmName = event.find('{urn:nortel:namespaces:mcp:faults}alarmName')
        if alarmName != None:
            alarmName = alarmName.text
        event_data.append(alarmName)

        csvwriter.writerow(event_data)

root = tree.getroot()
recurse(root)
sitescope_data.close()

更新

我无法以这种方式为另一个 XML 文件解析数据:

对于第一列,我想获取通用名称标签(recordingSystem、Ports 等)并将其与行标签中的子名称(closedFileCount、processedFileCount 等)连接起来

我注意到的问题是 subName 所在的标签一直在变化,它可能是“usage”、“lwGuage”、“hwGauge”等。我还需要收集这些并放在它旁边的列中。

请参阅下面的示例 XML:

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

<omGroups xmlns="urn:nortel:namespaces:mcp:oms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:nortel:namespaces:mcp:oms OMSchema.xsd" >

        <group>
                <name>RecordingSystem</name>
                <row>
                        <package>com.nortelnetworks.mcp.ne.base.recsystem.fw.system</package>
                        <class>RecSysFileOMRow</class>
                        <usage name="closedFileCount" hasThresholds="true">
                                <measures>
                                        closed file count
                                </measures>
                                <description>
                                        This register counts the number
                                        of closed files in the spool directory of a
                                        particular stream and a particular system.
                                        Files in the spool directory store the raw
                                        OAM records where they are sent to the
                                        Element Manager for formatting.
                                </description>
                                <notes>
                                        Minor and major alarms
                                        when the value of closedFileCount
                                        exceeds certain thresholds. Configure
                                        the threshold values for minor and major
                                        alarms for this OM through engineering
                                        parameters for minorBackLogCount and
                                        majorBackLogCount, respectively. These
                                        engineering parameters are grouped under
                                        the parameter group of Log, OM, and
                                        Accounting for the logs’ corresponding
                                        system.
                                </notes>
                        </usage>
                        <usage name="processedFileCount" hasThresholds="true">
                                <measures>
                                        Processed file count
                                </measures>
                                <description>
                                        The register counts the number
                                        of processed files in the spool directory of
                                        a particular stream and a particular system.
                                        Files in the spool directory store the raw
                                        OAM records and then send the records to
                                        the Element Manager for formatting.
                                </description>
                        </usage>
                </row>
                <documentation>
                        <description>
                                Rows of this OM group provide a count of the number of files contained
                                within the directory (which is the OM row key value).
                        </description>
                        <rowKey>
                                The full name of the directory containing the files counted by this row.
                        </rowKey>
                </documentation>
                <generatedOn>
                        <all/>
                </generatedOn>
        </group>
        <group traffic="true">
                <name>Ports</name>
                <row>
                        <package>com.nortelnetworks.ims.cap.mediaportal.host</package>
                        <class>PortsOMRow</class>
                        <usage name="rtpMpPortUsage">
                                <measures>
                                        BCP port usage
                                </measures>
                                <description>
                                        Meter showing number of ports in use.
                                </description>
                        </usage>
                        <lwGauge name="connMapEntriesLWM">
                                <measures>
                                        Lowest simultaneous port usage
                                </measures>
                                <description>
                                        Lowest number of
                                        simultaneous ports detected to be in
                                        use during the collection interval
                                </description>
                        </lwGauge>
                        <hwGauge name="connMapEntriesHWM">
                                <measures>
                                        Highest simultaneous port usage
                                </measures>
                                <description>
                                        Highest number of
                                        simultaneous ports detected to be in
                                        use during the collection interval.
                                </description>
                        </hwGauge>
                        <waterMark name="connMapEntries">
                                <measures>
                                        Connections map entries
                                </measures>
                                <description>
                                        Meter showing the number of connections in the host
                                        CPU connection map.
                                </description>
                                <bwg lwref="connMapEntriesLWM" hwref="connMapEntriesHWM"/>
                        </waterMark>
                        <counter name="portUsageSampleCnt">
                                <measures>
                                    Usage sample count
                                </measures>
                                <description>
                                    The number of 100-second samples taken during the
                                    collection interval contributing to the average report.
                                </description>
                        </counter>
                        <counter name="sampledRtpMpPortUsage">
                                <measures>
                                    In-use ports usage
                                </measures>
                                <description>
                                    Provides the sum of the in-use ports every 100 seconds.
                                </description>
                        </counter>
                        <precollector>
                                <package>com.nortelnetworks.ims.cap.mediaportal.host</package>
                                <class>PortsOMCenturyPrecollector</class>
                                <collector>centurySecond</collector>
                        </precollector>
                </row>
                <documentation>
                        <description>
                        </description>
                        <rowKey>
                        </rowKey>
                </documentation>
                <generatedOn>
                        <list>
                            <ne>sessmgr</ne>
                            <ne>rtpportal</ne>
                        </list>
                </generatedOn>
        </group>
       
</omGroups>

【问题讨论】:

    标签: python xml csv parsing elementtree


    【解决方案1】:

    诀窍是在递归时将家庭信息传递给孩子

    def recurse(root, family):
        for child in root:
            if child.tag == '{urn:nortel:namespaces:mcp:faults}family':
                family = child
            recurse(child, family)
        for event in root.findall('{urn:nortel:namespaces:mcp:faults}alarm'):
            if family:
                event_data = [family.attrib.get('longName',''), family.attrib.get('shortName', '')]
            else:
                event_data ['','']
    
    recurse(root,  None)
    

    一种更通用的方法是向下传递字典,但要注意,对字典的更改会冒泡,因此您最好在修改字典之前复制它:

    from copy import copy
    
    def recurse(root, props):
        for child in root:
            if child.tag == '{urn:nortel:namespaces:mcp:faults}family':
                p2 = copy(props)
                p2['shortName'] = child.attrib.get('shortName','')
                p2['longName'] = child.attrib.get('longName', '')
                recurse(child, p2)
            else:
                recurse(child, props)
        for event in root.findall('{urn:nortel:namespaces:mcp:faults}alarm'):
    
            event_data = [props.get('longName',''), props.get('shortName', '')]
    
    recurse(root,{})
    

    【讨论】:

    • 我有点困惑,这会填充 shortName 和 longName 列吗?我似乎无法让它正常工作。
    • 这两种方法都应该将 longName 和 shortName 放在 event_data 数组的前两个位置,因此当您附加到它并写出时,它们应该作为前两列出现。 - 你遇到了什么样的错误?
    • 看来我错误地将新代码放入原始代码中。我应该如何正确添加它?
    • 应该从def recurse(root):替换为event_data = []recurse(root,{})需要在最后替换recurse(root)
    • 你可以把工作外包给我 ;-) 但本质上,只需在同一级别的循环下方重复 for event in root.findall('{urn:nortel:namespaces:mcp:faults}alarm'): 中的代码,但对于 for event in root.findall('{urn:nortel:namespaces:mcp:faults}log'):
    猜你喜欢
    • 2021-10-29
    • 2011-03-05
    • 2015-10-28
    • 2014-11-22
    • 2017-04-18
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多