2

The XML data(file.xml) for the state will look like below

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<Activity_Logs xsi:schemaLocation="http://www.cisco.com/PowerKEYDVB/Auditing 
DailyActivityLog.xsd" To="2018-04-01" From="2018-04-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cisco.com/PowerKEYDVB/Auditing">
    <ActivityRecord>
       <time>2015-09-16T04:13:20Z</time>
       <oper>Create_Product</oper>
       <pkgEid>10</pkgEid>
       <pkgName>BBCWRL</pkgName>
       </ActivityRecord>
    <ActivityRecord>
       <time>2015-09-16T04:13:20Z</time>
       <oper>Create_Product</oper>
       <pkgEid>18</pkgEid>
       <pkgName>CNNINT</pkgName>
    </ActivityRecord>

Parsing and conversion to CSV of above mentioned XML file will be done by the following python code.

import csv
import xml.etree.cElementTree as ET


tree =  ET.parse('file.xml')
root = tree.getroot()


data_to_csv= open('output.csv','w')

list_head=[]

Csv_writer=csv.writer(data_to_csv)

count=0
for elements in root.findall('ActivityRecord'):
    List_node = []
    if count == 0 :

        time = elements.find('time').tag
        list_head.append(time)

        oper = elements.find('oper').tag
        list_head.append(oper)

        pkgEid = elements.find('pkgEid').tag
        list_head.append(pkgEid)


        pkgName = elements.find('pkgName').tag
        list_head.append(pkgName)

        Csv_writer.writerow(list_head)
        count = +1

    time = elements.find('time').text
    List_node.append(time)

    oper = elements.find('oper').text
    List_node.append(oper)

    pkgEid = elements.find('pkgEid').text
    List_node.append(pkgEid)

    pkgName = elements.find('pkgName').text
    List_node.append(pkgName)    

    Csv_writer.writerow(List_node)

data_to_csv.close()

The code I am using is not giving me any data in CSV. Could some one tell me where excatly am I going wrong?

2
  • what elements you want to extract from xml file? Please specify more details. Commented Apr 18, 2018 at 11:46
  • time, oper, pkgEid, pkgName are the elements I want to extract Commented Apr 18, 2018 at 12:12

5 Answers 5

6

Using pandas and BeautifulSoup you can achieve your expected output easily:

#Code:

import pandas as pd
import itertools
from bs4 import BeautifulSoup as b
with open("file.xml", "r") as f: # opening xml file
    content = f.read()

soup = b(content, "lxml")
pkgeid =  [ values.text for values in soup.findAll("pkgeid")]
pkgname = [ values.text for values in soup.findAll("pkgname")]
time =  [ values.text for values in soup.findAll("time")]
oper =  [ values.text for values in soup.findAll("oper")]
# For python-3.x use `zip_longest` method
# For python-2.x use 'izip_longest method
data = [item for item in itertools.zip_longest(time, oper, pkgeid, pkgname)] 
df  = pd.DataFrame(data=data)
df.to_csv("sample.csv",index=False, header=None)

#output in `sample.csv` file will be as follows:
2015-09-16T04:13:20Z,Create_Product,10,BBCWRL
2015-09-16T04:13:20Z,Create_Product,18,CNNINT
2018-04-01T03:30:28Z,Deactivate_Dhct,,
Sign up to request clarification or add additional context in comments.

15 Comments

I get this error AttributeError: 'NoneType' object has no attribute 'text'
As down the XML there are times when 'pkgeid' could be blank
if it is blank then the field will be empty
Also please check filename, in my code it was different filename though i changed it
<ActivityRecord> <time>2018-04-01T03:30:28Z</time> <oper>Deactivate_Dhct</oper> <dhct>18:55:0F:47:03:2D</dhct> </ActivityRecord>
|
6

Using Pandas, parsing all xml fields.

import xml.etree.ElementTree as ET
import pandas as pd

tree = ET.parse("file.xml")
root = tree.getroot()

get_range = lambda col: range(len(col))
l = [{r[i].tag:r[i].text for i in get_range(r)} for r in root]

df = pd.DataFrame.from_dict(l)
df.to_csv('file.csv')

Comments

3

Answer for 2021:
you can use Pandas to read XML and output CSV
https://pandas.pydata.org/pandas-docs/dev/whatsnew/v1.3.0.html#read-and-write-xml-documents

import pandas as pd
df = pd.read_xml(<xml_or_xml_filepath>)
# ...
df.to_csv(<csv_filepath>)

for more details on usage see official documentation: https://pandas.pydata.org/pandas-docs/dev/reference/api/pandas.read_xml.html

Comments

1

Use pyxmlparser if it is a one-time operation.

Disclaimer I am the author of the library and it is fairly new. Any feedback is appreciated. It is a command line utility.

https://pypi.org/project/pyxmlparser/

1 Comment

oww, you did not provide examples of usage
1

Found the most appropriate way of doing this:

import os
import pandas as pd
from bs4 import BeautifulSoup as b

with open("file.xml", "r") as f: # opening xml file
    content = f.read()

soup = b(content, "lxml")
df1 = pd.DataFrame()

for each_file in files_xlm: 
    with open( each_file, "r") as f: # opening xml file
        content = f.read()
    soup = b(content, "lxml")    

    list1 = []
    for values in soup.findAll("activityrecord"):  
        if values.find("time") is None:
            time = ""
        else:
            time = values.find("time").text        
        if values.find("oper") is None:
            oper = ""    
        else:
            oper = values.find("oper").text      
        if values.find("pkgeid") is None:
            pkgeid = ""    
        else:
            pkgeid = values.find("pkgeid").text     
        if values.find("pkgname") is None:
            pkgname = ""    
        else:
            pkgname = values.find("pkgname").text 
        if values.find("dhct") is None:
            dhct = ""    
        else:
            dhct = values.find("dhct").text   
        if values.find("sourceid") is None:
            sourceid = ""    
        else:
            sourceid = values.find("sourceid").text      
    
        list1.append(time+','+ oper+','+pkgeid+','+ pkgname+','+dhct+','+sourceid)
        df = pd.DataFrame(list1)



df=df[0].str.split(',', expand=True)
df.columns = ['Time','Oper','PkgEid','PkgName','dhct','sourceid']
df.to_csv("new.csv",index=False)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.