Python re.findall organize list - python

I have a text file with entries like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Applications_GetResponse xmlns="http://www.country.com">
<Applications>
<CS_Application>
<Name>Spain</Name>
<Key>2345364564</Key>
<Status>NORMAL</Status>
<Modules>
<CS_Module>
<Name>zaragoza</Name>
<Key>8743249725</Key>
<DevelopmentEffort>0</DevelopmentEffort>
<LogicalDBConnections/>
</CS_Module>
<CS_Module>
<Name>malaga</Name>
<Key>8743249725</Key>
<DevelopmentEffort>0</DevelopmentEffort>
<LogicalDBConnections/>
</CS_Module>
</Modules>
<CreatedBy>7</CreatedBy>
</CS_Application>
<CS_Application>
<Name>UK</Name>
<Key>2345364564</Key>
<Status>NORMAL</Status>
<Modules>
<CS_Module>
<Name>london</Name>
<Key>8743249725</Key>
<DevelopmentEffort>0</DevelopmentEffort>
<LogicalDBConnections/>
</CS_Module>
<CS_Module>
<Name>liverpool</Name>
<Key>8743249725</Key>
<DevelopmentEffort>0</DevelopmentEffort>
<LogicalDBConnections/>
</CS_Module>
</Modules>
<CreatedBy>7</CreatedBy>
</CS_Application>
</Applications>
</Applications_GetResponse>
</soap:Body>
</soap:Envelope>
I would like to analyze it and obtain the name of the country in the sequence of the cities.
I tried some things with python re.finall, but I didn't get anything like it
print("HERE APPLICATIONS")
applications = re.findall('<CS_Application><Name>(.*?)</Name>', response_apply.text)
print(applications)
print("HERE MODULES")
modules = re.findall('<CS_Module><Name>(.*?)</Name>', response_apply.text)
print(modules)
return:
host-10$ sudo python3 capture.py
HERE APPLICATIONS
['Spain', 'UK']
HERE MODULES
['zaragoza', 'malaga', 'london', 'liverpool']
The expected result is, I would like the result to be like this:
HERE
The Country: Spain - Cities: zaragoza,malaga
The Country: UK - Cities: london,liverpool

Regex is not good to parse xml. Better use xml parser..
If you want regex solution then hope below code help you.
import re
s = """\n<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">\n <soap:Body>\n <Applications_GetResponse xmlns="http://www.country.com">\n <Applications>\n <CS_Application>\n <Name>Spain</Name>\n <Key>2345364564</Key>\n <Status>NORMAL</Status>\n <Modules>\n <CS_Module>\n <Name>zaragoza</Name>\n <Key>8743249725</Key>\n <DevelopmentEffort>0</DevelopmentEffort>\n <LogicalDBConnections/>\n </CS_Module>\n <CS_Module>\n <Name>malaga</Name>\n <Key>8743249725</Key>\n <DevelopmentEffort>0</DevelopmentEffort>\n <LogicalDBConnections/>\n </CS_Module>\n </Modules>\n <CreatedBy>7</CreatedBy>\n </CS_Application>\n <CS_Application>\n <Name>UK</Name>\n <Key>2345364564</Key>\n <Status>NORMAL</Status>\n <Modules>\n <CS_Module>\n <Name>london</Name>\n <Key>8743249725</Key>\n <DevelopmentEffort>0</DevelopmentEffort>\n <LogicalDBConnections/>\n </CS_Module>\n <CS_Module>\n <Name>liverpool</Name>\n <Key>8743249725</Key>\n <DevelopmentEffort>0</DevelopmentEffort>\n <LogicalDBConnections/>\n </CS_Module>\n </Modules>\n <CreatedBy>7</CreatedBy>\n </CS_Application>\n </Applications>\n </Applications_GetResponse>\n </soap:Body>\n</soap:Envelope>\n"""
pattern1 = re.compile(r'<CS_Application>([\s\S]*?)</CS_Application>')
pattern2 = re.compile(r'<Name>(.*)?</Name>')
for m in re.finditer(pattern1, s):
ss = m.group(1)
res = []
for mm in re.finditer(pattern2, ss):
res.append(mm.group(1))
print("The Country: "+res[0]+" - Cities: "+",".join(res[1:len(res)]))

Related

Create dataframe of certain XML element's text python pandas

I am trying to create a dataframe out the XML code as shown below
<Structure>
<Field>
<Field_Name>GAMEREF</Field_Name>
<Field_Type>Numeric</Field_Type>
<Field_Len>4</Field_Len>
<Field_Dec>0</Field_Dec>
</Field>
...
<Field>
<Field_Name>WINLOSS</Field_Name>
<Field_Type>Character</Field_Type>
<Field_Len>1</Field_Len>
<Field_Dec>0</Field_Dec>
</Field>
</Structure>
<Records>
<Record>
<GAMEREF>1217</GAMEREF>
<YEAR>2021</YEAR>
(MORE ELEMENTS I DO NOT CARE ABOUT)
<GAMENO>1</GAMENO>
<WINLOSS>W</WINLOSS>
</Record>
...
<Record>
<GAMEREF>1220</GAMEREF>
<YEAR>2021</YEAR>
(MORE ELEMENTS I DO NOT CARE ABOUT)
<GAMENO>4</GAMENO>
<WINLOSS>L</WINLOSS>
</Record>
</Records>
The structure section of the XML code that is irrelevant to the dataframe I am trying to create.
I am trying to only use the XML elements of GAMEREF, YEAR, GAMENO, and WINLOSS as there are more in the XML for the Record elements.
I have tried using code as shown below to get this to work, but when I run the code I get the error of "AttributeError: 'NoneType' object has no attribute 'text'"
Code is below.
import pandas as pd
import xml.etree.ElementTree as et
xtree = et.parse("gamedata.xml")
xroot = xtree.getroot()
df_cols = ["GAME REF","YEAR", "GAME NO", "WIN LOSS"]
rows = []
for child in xroot.iter():
s_gameref = child.find('GAMEREF').text,
s_year = child.find('YEAR').text,
s_game_no = child.find('GAMENO').text,
s_winloss = child.find('WINLOSS').text
rows.append({"GAME REF": s_gameref,"YEAR": s_year,
"GAME NO": s_game_no, "WIN LOSS": s_winloss})
df = pd.DataFrame(rows, columns = df_cols)
The code is based off other stuff I have seen on the Stack and other sites, but nothing is working yet.
Ideal dataframe output is below
GAME REF
YEAR
GAME NO
WIN LOSS
1217
2021
1
W
1218
2021
2
W
1219
2021
3
L
1220
2021
4
L
Thanks
EDIT - NOT SURE WHAT IS GOING ON WITH MY TABLE, BUT IT SHOULD LOOK LIKE THIS
I think the below is what you are looking for. (Just loop over the "interesting" sub elements of Record). The logic of the code is in the line that starts with data = [.... The 2 loops can be found there.
import pandas as pd
import xml.etree.ElementTree as ET
xml = '''<r><Structure>
<Field>
<Field_Name>GAMEREF</Field_Name>
<Field_Type>Numeric</Field_Type>
<Field_Len>4</Field_Len>
<Field_Dec>0</Field_Dec>
</Field>
...
<Field>
<Field_Name>WINLOSS</Field_Name>
<Field_Type>Character</Field_Type>
<Field_Len>1</Field_Len>
<Field_Dec>0</Field_Dec>
</Field>
</Structure>
<Records>
<Record>
<GAMEREF>1217</GAMEREF>
<YEAR>2021</YEAR>
<GAMENO>1</GAMENO>
<WINLOSS>W</WINLOSS>
</Record>
<Record>
<GAMEREF>1220</GAMEREF>
<YEAR>2021</YEAR>
<GAMENO>4</GAMENO>
<WINLOSS>L</WINLOSS>
</Record>
</Records></r>'''
fields = {'GAMEREF':'GAME REF', 'YEAR':'YEAR', 'GAMENO':'GAME NO','WINLOSS':'WIN LOSS'}
root = ET.fromstring(xml)
data = [{display_name: rec.find(element_name).text for element_name,display_name in fields.items()} for rec in root.findall('.//Record')]
df = pd.DataFrame(data)
print(df)
output
GAME REF YEAR GAME NO WIN LOSS
0 1217 2021 1 W
1 1220 2021 4 L
import pandas as pd
import xml.etree.ElementTree as et
xtree = et.parse("gamedata.xml")
xroot = xtree.getroot()
df_cols = ["GAME REF","YEAR", "GAME NO", "WIN LOSS"]
rows = []
for record in xroot:
s_gameref = record.find('GAMEREF').text
s_year = record.find('YEAR').text
s_game_no = record.find('GAMENO').text
s_winloss = record.find('WINLOSS').text
rows.append({"GAME REF": s_gameref,"YEAR": s_year,
"GAME NO": s_game_no, "WIN LOSS": s_winloss})
df = pd.DataFrame(rows, columns = df_cols)
Remove .iter()

Building XML from excel data with Python

I am trying to build an xml file from an excel spreadsheet using python but am having trouble building the structure. The xml schema is unique to a software so the opening few tags and ending few would be easier to be written to the xml file just as variables, shown below. They are constant so are pulled from the "
I believe the script neeeds to loop through another sheet, being the ".XML Framework" sheet to build the .xml structure as these are the values which will be ultimately changing. The structure of this sheet is provided below.
here is the .xml structure, from which the python is outputting well up to the unique values, and the changing values are shown in bold. This shows just one row of the data from the workbook. When the workbook has a second row, the .xml structure repeats again where it starts with .
The data structure in the excel sheet ".XML Framework" is:
col 1 = **equals**
col 2 = **74**
col 3 = **Data**"
col 4 = col 3
col 5 = **Name 07**
col 6 = col 5
col 7 = **wstring**
col 8 = /**SM15-HVAC-SUPP-TM-37250-ST**
THIS IS THE DESIRED XML STRUCTURE
<?xml version="1.0" encoding="UTF-8" ?>
<exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://download.autodesk.com/us/navisworks/schemas/nw-exchange-12.0.xsd" units="m" filename="" filepath="">
<selectionsets>
<selectionset name="Dev_1">
<findspec mode="all" disjoint="0">
<conditions>
<condition test="**equals**" flags="**74**">
<category>
<name internal="**Data**">**Data**</name>
</category>
<property>
<name internal="**Name 07**">**Name 07**</name>
</property>
<value>
<data type="**wstring**">/**SM15-HVAC-SUPP-TM-37250-ST**</data>
</value>
</condition>
</conditions>
<locator>/</locator>
</findspec>
</exchange>
Here is my attempt from the python:
path = (r"C:\\Users\\ciara\\desktop\\")
book = os.path.join(path + "Search_Set.xlsm")
wb = openpyxl.load_workbook(book)
sh = wb.get_sheet_by_name('.XML Framework')
df1 = pd.read_excel(book, "<CLEAN>", header=None)
#opening 5 lines of .xml search
print(df1)
cV1 = df1.iloc[0,0] #xml header
print (cV1)
cV2 = df1.iloc[1,0] #<exchange>
print (cV2)
cV3 = df1.iloc[2,0] #<selectionsets>
print (cV3)
cV4 = df1.iloc[3,0] #<selection set name>
print (cV4)
cV5 = df1.iloc[4,0] #<findspec mode>
print (cV5)
cV6 = df1.iloc[5,0] #<findspec mode>
print (cV6)
E = lxml.builder.ElementMaker()
root = ET.Element(cV1)
doc0 = ET.SubElement(root, cV2)
doc1 = ET.SubElement(doc0, cV3)
doc2 = ET.SubElement(doc1, cV4)
doc3 = ET.SubElement(doc2, cV5)
doc4 = ET.SubElement(doc3, cV6)
the_doc = root(
doc0(
doc1(
doc2(
doc3(
FIELD1('condition test=', name='blah'),
FIELD2('some value2', name='asdfasd'),
)
)
)
)
)
print (lxml.etree.tostring(the_doc, pretty_print=True))
tree = ET.ElementTree(root)
tree.write("filename.xml")

How to iterate over XML tags in Python using ElementTree & save to CSV

I am trying to iterate over all nodes & child nodes in a tree using ElementTree. I would like to get the all the parent & its child XML tags as columns and values which could append the child nodes to parent in CSV format. I am using python 2.7. The header should be printed only once & below should be respective values
XML File :
<Customers>
<Customer CustomerID="GREAL">
<CompanyName>Great Lakes Food Market</CompanyName>
<ContactName>Howard Snyder</ContactName>
<ContactTitle>Marketing Manager</ContactTitle>
<Phone>(503) 555-7555</Phone>
<FullAddress>
<Address>2732 Baker Blvd.</Address>
<City>Eugene</City>
<Region>OR</Region>
<PostalCode>97403</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
<Customer CustomerID="HUNGC">
<CompanyName>Hungry Coyote Import Store</CompanyName>
<ContactName>Yoshi Latimer</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<Phone>(503) 555-6874</Phone>
<Fax>(503) 555-2376</Fax>
<FullAddress>
<Address>City Center Plaza 516 Main St.</Address>
<City>Elgin</City>
<Region>OR</Region>
<PostalCode>97827</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
<Customer CustomerID="LAZYK">
<CompanyName>Lazy K Kountry Store</CompanyName>
<ContactName>John Steel</ContactName>
<ContactTitle>Marketing Manager</ContactTitle>
<Phone>(509) 555-7969</Phone>
<Fax>(509) 555-6221</Fax>
<FullAddress>
<Address>12 Orchestra Terrace</Address>
<City>Walla Walla</City>
<Region>WA</Region>
<PostalCode>99362</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
<Customer CustomerID="LETSS">
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<ContactTitle>Owner</ContactTitle>
<Phone>(415) 555-5938</Phone>
<FullAddress>
<Address>87 Polk St. Suite 5</Address>
<City>San Francisco</City>
<Region>CA</Region>
<PostalCode>94117</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
</Customers>
My Code:
#Import Libraries
import csv
import xmlschema
import xml.etree.ElementTree as ET
#Define the variable to store the XML Document
xml_file = 'C:/Users/391648/Desktop/BOSS_20190618_20190516_18062019141928_CUMA/source_Files_XML/CustomersOrders.xml'
#using XML Schema Library validate the XML against XSD
my_schema = xmlschema.XMLSchema('C:/Users/391648/Desktop/BOSS_20190618_20190516_18062019141928_CUMA/source_Files_XML/CustomersOrders.xsd')
SchemaCheck = my_schema.is_valid(xml_file)
print(SchemaCheck) #Prints as True if the document is validated with XSD
#Parse XML & get root
tree = ET.parse(xml_file)
root = tree.getroot()
#Create & Open CSV file
xml_data_to_csv = open('C:/Users/391648/Desktop/BOSS_20190618_20190516_18062019141928_CUMA/source_Files_XML/PythonXMl.csv','w')
#create variable to write to csv
csvWriter = csv.writer(xml_data_to_csv)
#Create list contains header
count =0
#Loop for each node
for element in root.findall('Customers/Customer'):
List_nodes = []
#Get head by Tag
if count ==0:
list_header =[]
Full_Address = []
CompanyName = element.find('CompanyName').tag
list_header.append(CompanyName)
ContactName = element.find('ContactName').tag
list_header.append(ContactName)
ContactTitle = element.find('ContactTitle').tag
list_header.append(ContactTitle)
Phone = element.find('Phone').tag
list_header.append(Phone)
print(list_header)
csvWriter.writerow(list_header)
count = count + 1
#Get the data of the Node
CompanyName = element.find('CompanyName').text
List_nodes.append(CompanyName)
ContactName = element.find('ContactName').text
List_nodes.append(ContactName)
ContactTitle = element.find('ContactTitle').text
List_nodes.append(ContactTitle)
Phone = element.find('Phone').text
List_nodes.append(Phone)
print(List_nodes)
#Write List_Nodes to CSV
csvWriter.writerow(List_nodes)
xml_data_to_csv.close()
Expected CSV output:
CompanyName,ContactName,ContactTitle,Phone, Address, City, Region, PostalCode, Country
Great Lakes Food Market,Howard Snyder,Marketing Manager,(503) 555-7555, City Center Plaza 516 Main St., Elgin, OR, 97827, USA
Hungry Coyote Import Store,Yoshi Latimer,Sales Representative,(503) 555-6874, 12 Orchestra Terrace, Walla Walla, WA, 99362, USA
You might be better off using lxml. It has most of the desired functionality for finding elements built in.
from lxml import etree
import csv
with open('file.xml') as fp:
xml = etree.fromstring(fp.read())
field_dict = {
'CompanyName': 'CompanyName',
'ContactName': 'ContactName',
'ContactTitle': 'ContactTitle',
'Phone': 'Phone',
'Address': 'FullAddress/Address',
'City': 'FullAddress/City',
'Region': 'FullAddress/Region',
'PostalCode': 'FullAddress/PostalCode',
'Country': 'FullAddress/Country'
}
customers = []
for customer in xml:
line = {k: customer.find(v).text for k, v in field_dict.items()}
customers.append(line)
with open('customers.csv', 'w') as fp:
writer = csv.DictWriter(fp, field_dict)
writer.writerows(customers)
You can use xmltodict to convert data to JSON format instead of parsing XML:
import xmltodict
import pandas as pd
with open('data.xml', 'r') as f:
data = xmltodict.parse(f.read())['Customers']['Customer']
data_pd = {'CompanyName': [i['CompanyName'] for i in data],
'ContactName': [i['ContactName'] for i in data],
'ContactTitle': [i['ContactTitle'] for i in data],
'Phone': [i['Phone'] for i in data],
'Address': [i['FullAddress']['Address'] for i in data],
'City': [i['FullAddress']['City'] for i in data],
'Region': [i['FullAddress']['Region'] for i in data],
'PostalCode': [i['FullAddress']['PostalCode'] for i in data],
'Country': [i['FullAddress']['Country'] for i in data]}
df = pd.DataFrame(data_pd)
df.to_csv('result.csv', index=False)
Output CSV file:
CompanyName,ContactName,ContactTitle,Phone,Address,City,Region,PostalCode,Country
Great Lakes Food Market,Howard Snyder,Marketing Manager,(503) 555-7555,2732 Baker Blvd.,Eugene,OR,97403,USA
Hungry Coyote Import Store,Yoshi Latimer,Sales Representative,(503) 555-6874,City Center Plaza 516 Main St.,Elgin,OR,97827,USA
Lazy K Kountry Store,John Steel,Marketing Manager,(509) 555-7969,12 Orchestra Terrace,Walla Walla,WA,99362,USA
Let's Stop N Shop,Jaime Yorres,Owner,(415) 555-5938,87 Polk St. Suite 5,San Francisco,CA,94117,USA
A couple of things I have changed:
Removed schema validation since I do not have the XSD. You may include it
Made the child node traversal dynamic instead of statically referring each child node
The main for loop condition changed to for customer in root.findall('Customer') from for customer in root.findall('Customers/Customer')
However, I tried to keep your program structure, library usage intact. Here is the modified program:
import xml.etree.ElementTree as et
import csv
tree = et.parse("../data/customers.xml")
root = tree.getroot()
headers = []
count = 0
xml_data_to_csv = open('../data/customers.csv', 'w')
csvWriter = csv.writer(xml_data_to_csv)
for customer in root.findall('Customer'):
data = []
for detail in customer:
if(detail.tag == 'FullAddress'):
for addresspart in detail:
data.append(addresspart.text.rstrip('/n/r'))
if(count == 0):
headers.append(addresspart.tag)
else:
data.append(detail.text.rstrip('/n/r'))
if(count == 0):
headers.append(detail.tag)
if(count == 0):
csvWriter.writerow(headers)
csvWriter.writerow(data)
count = count + 1
With the given input XML content it produces:
CompanyName,ContactName,ContactTitle,Phone,Address,City,Region,PostalCode,Country
Great Lakes Food Market,Howard Snyde,Marketing Manage,(503) 555-7555,2732 Baker Blvd.,Eugene,OR,97403,USA
Hungry Coyote Import Store,Yoshi Latime,Sales Representative,(503) 555-6874,(503) 555-2376,City Center Plaza 516 Main St.,Elgi,OR,97827,USA
Lazy K Kountry Store,John Steel,Marketing Manage,(509) 555-7969,(509) 555-6221,12 Orchestra Terrace,Walla Walla,WA,99362,USA
Let's Stop N Shop,Jaime Yorres,Owne,(415) 555-5938,87 Polk St. Suite 5,San Francisco,CA,94117,USA
Note: Instead of writing to CSV in the loop you may append to an array and write it at one go. It depends on your content size and performance.
Update: When you have customers and their orders in the XML
The XML processing and CSV writing code structure remains the same. Additionally, process Orders element while processing customers. Now, under Orders Order elements can be processed exactly like Customer. As you mentioned each Order has ShipInfo as well.
The input XML is assumed to be (based on the comment below):
<Customers>
<Customer CustomerID="GREAL">
<CompanyName>Great Lakes Food Market</CompanyName>
<ContactName>Howard Snyder</ContactName>
<ContactTitle>Marketing Manager</ContactTitle>
<Phone>(503) 555-7555</Phone>
<FullAddress>
<Address>2732 Baker Blvd.</Address>
<City>Eugene</City>
<Region>OR</Region>
<PostalCode>97403</PostalCode>
<Country>USA</Country>
</FullAddress>
<Orders>
<Order>
<Param1>Value1</Param1>
<Param2>Value2</Param2>
<ShipInfo>
<ShipInfoParam1>Value3</ShipInfoParam1>
<ShipInfoParam2>Value4</ShipInfoParam2>
</ShipInfo>
</Order>
<Order>
<Param1>Value5</Param1>
<Param2>Value6</Param2>
<ShipInfo>
<ShipInfoParam1>Value7</ShipInfoParam1>
<ShipInfoParam2>Value8</ShipInfoParam2>
</ShipInfo>
</Order>
</Orders>
</Customer>
<Customer CustomerID="HUNGC">
<CompanyName>Hungry Coyote Import Store</CompanyName>
<ContactName>Yoshi Latimer</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<Phone>(503) 555-6874</Phone>
<Fax>(503) 555-2376</Fax>
<FullAddress>
<Address>City Center Plaza 516 Main St.</Address>
<City>Elgin</City>
<Region>OR</Region>
<PostalCode>97827</PostalCode>
<Country>USA</Country>
</FullAddress>
<Orders>
<Order>
<Param1>Value7</Param1>
<Param2>Value8</Param2>
<ShipInfo>
<ShipInfoParam1>Value9</ShipInfoParam1>
<ShipInfoParam2>Value10</ShipInfoParam2>
</ShipInfo>
</Order>
</Orders>
</Customer>
<Customer CustomerID="LAZYK">
<CompanyName>Lazy K Kountry Store</CompanyName>
<ContactName>John Steel</ContactName>
<ContactTitle>Marketing Manager</ContactTitle>
<Phone>(509) 555-7969</Phone>
<Fax>(509) 555-6221</Fax>
<FullAddress>
<Address>12 Orchestra Terrace</Address>
<City>Walla Walla</City>
<Region>WA</Region>
<PostalCode>99362</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
<Customer CustomerID="LETSS">
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<ContactTitle>Owner</ContactTitle>
<Phone>(415) 555-5938</Phone>
<FullAddress>
<Address>87 Polk St. Suite 5</Address>
<City>San Francisco</City>
<Region>CA</Region>
<PostalCode>94117</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
</Customers>
Here is the modified code that process both customers and orders:
import xml.etree.ElementTree as et
import csv
tree = et.parse("../data/customers-with-orders.xml")
root = tree.getroot()
customer_csv = open('../data/customers-part.csv', 'w')
order_csv = open('../data/orders-part.csv', 'w')
customerCsvWriter = csv.writer(customer_csv)
orderCsvWriter = csv.writer(order_csv)
customerHeaders = []
orderHeaders = ['CustomerID']
isFirstCustomer = True
isFirstOrder = True
def processOrders(customerId):
global isFirstOrder
for order in detail.findall('Order'):
orderData = [customerId]
for orderdetail in order:
if(orderdetail.tag == 'ShipInfo'):
for shipinfopart in orderdetail:
orderData.append(shipinfopart.text.rstrip('/n/r'))
if(isFirstOrder):
orderHeaders.append(shipinfopart.tag)
else:
orderData.append(orderdetail.text.rstrip('/n/r'))
if(isFirstOrder):
orderHeaders.append(orderdetail.tag)
if(isFirstOrder):
orderCsvWriter.writerow(orderHeaders)
orderCsvWriter.writerow(orderData)
isFirstOrder = False
for customer in root.findall('Customer'):
customerData = []
customerId = customer.get('CustomerID')
for detail in customer:
if(detail.tag == 'FullAddress'):
for addresspart in detail:
customerData.append(addresspart.text.rstrip('/n/r'))
if(isFirstCustomer):
customerHeaders.append(addresspart.tag)
elif(detail.tag == 'Orders'):
processOrders(customerId)
else:
customerData.append(detail.text.rstrip('/n/r'))
if(isFirstCustomer):
customerHeaders.append(detail.tag)
if(isFirstCustomer):
customerCsvWriter.writerow(customerHeaders)
customerCsvWriter.writerow(customerData)
isFirstCustomer = False
Output produced in customers-part.csv:
CompanyName,ContactName,ContactTitle,Phone,Address,City,Region,PostalCode,Country
Great Lakes Food Market,Howard Snyde,Marketing Manage,(503) 555-7555,2732 Baker Blvd.,Eugene,OR,97403,USA
Hungry Coyote Import Store,Yoshi Latime,Sales Representative,(503) 555-6874,(503) 555-2376,City Center Plaza 516 Main St.,Elgi,OR,97827,USA
Lazy K Kountry Store,John Steel,Marketing Manage,(509) 555-7969,(509) 555-6221,12 Orchestra Terrace,Walla Walla,WA,99362,USA
Let's Stop N Shop,Jaime Yorres,Owne,(415) 555-5938,87 Polk St. Suite 5,San Francisco,CA,94117,USA
Output produced in orders-part.csv:
CustomerID,Param1,Param2,ShipInfoParam1,ShipInfoParam2
GREAL,Value1,Value2,Value3,Value4
GREAL,Value5,Value6,Value7,Value8
HUNGC,Value7,Value8,Value9,Value10
Note: the code can be optimized further by reusing. I am leaving that part to you. Secondly, notice that in each order customer Id is added in order to distinguish.

Python 3: XML Tag Value not being written to csv file

My python 3 script takes an xml file and creates a csv file.
Small excerpt of xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<metadata>
<dc>
<title>Golden days for boys and girls, 1895-03-16, v. XVI #17</title>
<subject>Children's literature--Children's periodicals</subject>
<description>Archives & Special Collections at the Thomas J. Dodd Research Center, University of Connecticut Libraries</description>
<publisher>James Elverson, 1880-</publisher>
<date>1895-06-15</date>
<type>Text | periodicals</type>
<format>image/jp2</format>
<handle>http://hdl.handle.net/11134/20002:860074494</handle>
<accessionNumber/>
<barcode/>
<identifier>20002:860074494 | local: 868010272 | local: 997186613502432 | local: 39153019382870 | hdl:  | http://hdl.handle.net/11134/20002:860074494</identifier>
<rights>These Materials are provided for educational and research purposes only. The University of Connecticut Libraries hold the copyright except where noted. Permission must be obtained in writing from the University of Connecticut Libraries and/or theowner(s) of the copyright to publish reproductions or quotations beyond "fair use." | The collection is open and available for research.</rights>
<creator/>
<relation/>
<coverage/>
<language/>
</dc>
</metadata>
Python3 code:
import csv
import xml.etree.ElementTree as ET
tree = ET.ElementTree(file='ctda_set1_uniqueTags.xml')
doc = ET.parse("ctda_set1_uniqueTags.xml")
root = tree.getroot()
oaidc_data = open('ctda_set1_uniqueTags.csv', 'w', encoding='utf-8')
titles = 'dc/title'
subjects = 'dc/subject'
csvwriter = csv.writer(oaidc_data)
oaidc_head = ['Title', 'Subject', 'Description', 'Publisher', 'Date', 'Type', 'Format', 'Handle', 'Accession Number', 'Barcode', 'Identifiers', 'Rights', 'Creator', 'Relation', 'Coverage', 'Language']
count = 0
for member in root.findall('dc'):
if count == 0:
csvwriter.writerow(oaidc_head)
count = count + 1
dcdata = []
titles = member.find('title').text
dcdata.append(titles)
subjects = member.find('subject').text
dcdata.append(subjects)
descriptions = member.find('description').text
dcdata.append(descriptions)
publishers = member.find('publisher').text
dcdata.append(publishers)
dates = member.find('date').text
dcdata.append(dates)
types = member.find('type').text
dcdata.append(types)
formats = member.find('format').text
dcdata.append(formats)
handle = member.find('handle').text
dcdata.append(handle)
accessionNo = member.find('accessionNumber').text
dcdata.append(accessionNo)
barcodes = member.find('barcode').text
dcdata.append(barcodes)
identifiers = member.find('identifier').text
dcdata.append(identifiers)
rt = member.find('rights').text
print(member.find('rights').text)
dcdata.append('rt')
ct = member.find('creator').text
dcdata.append('ct')
rt = member.find('relation').text
dcdata.append('rt')
ce = member.find('coverage').text
dcdata.append('ce')
lang = member.find('language').text
dcdata.append('lang')
csvwriter.writerow(dcdata)
oaidc_data.close()
Everything works as expected except for rt, ce, and lang. What happens is that in the csv, all the data is written with the comma delimiter. For rt, the value is always rt, for ce, ce, lang, lang, etc.
Here's a snippet of the output:
Title,Subject,Description,Publisher,Date,Type,Format,Handle,Accession Number,Barcode,Identifiers,Rights,Creator,Relation,Coverage,Language
"Golden days for boys and girls, 1895-03-16, v. XVI #17",Children's literature--Children's periodicals,"Archives & Special Collections at the Thomas J. Dodd Research Center, University of Connecticut Libraries","James Elverson, 1880-",1895-06-15,Text | periodicals,image/jp2,hdl.handle.net/11134/20002:860074494,,,20002:860074494 | local: 868010272 | local: 997186613502432 | local: 39153019382870,**rt,ct,rt,ce,lang**
Some of the rights statements get very long - perhaps that's the issue. That's why I added the print(member.find('rights')) to see the output. The text is printed just fine. The text just isn't written to the csv. What I'd like is to have the value or text written for these xml tags. Any help would be appreciated.
Thanks.
Jennifer
In the line dcdata.append('rt') there is no need for the quotes. Try dcdata.append(rt). Similarly, there are unnecessary quotes in the ce and lang lines.

python read complex xml with ElementTree

I am trying to parse this xml file with python element tree:
<?xml version="1.0" encoding="Windows-1250"?>
<rsp:responsePack version="2.0" id="001" state="ok" note="" programVersion="9801.8 (19.5.2011)" xmlns:rsp="http://www.stormware.cz/schema/version_2/response.xsd" xmlns:rdc="http://www.stormware.cz/schema/version_2/documentresponse.xsd" xmlns:typ="http://www.stormware.cz/schema/version_2/type.xsd" xmlns:lst="http://www.stormware.cz/schema/version_2/list.xsd" xmlns:lStk="http://www.stormware.cz/schema/version_2/list_stock.xsd" xmlns:lAdb="http://www.stormware.cz/schema/version_2/list_addBook.xsd" xmlns:acu="http://www.stormware.cz/schema/version_2/accountingunit.xsd" xmlns:inv="http://www.stormware.cz/schema/version_2/invoice.xsd" xmlns:vch="http://www.stormware.cz/schema/version_2/voucher.xsd" xmlns:int="http://www.stormware.cz/schema/version_2/intDoc.xsd" xmlns:stk="http://www.stormware.cz/schema/version_2/stock.xsd" xmlns:ord="http://www.stormware.cz/schema/version_2/order.xsd" xmlns:ofr="http://www.stormware.cz/schema/version_2/offer.xsd" xmlns:enq="http://www.stormware.cz/schema/version_2/enquiry.xsd" xmlns:vyd="http://www.stormware.cz/schema/version_2/vydejka.xsd" xmlns:pri="http://www.stormware.cz/schema/version_2/prijemka.xsd" xmlns:bal="http://www.stormware.cz/schema/version_2/balance.xsd" xmlns:pre="http://www.stormware.cz/schema/version_2/prevodka.xsd" xmlns:vyr="http://www.stormware.cz/schema/version_2/vyroba.xsd" xmlns:pro="http://www.stormware.cz/schema/version_2/prodejka.xsd" xmlns:con="http://www.stormware.cz/schema/version_2/contract.xsd" xmlns:adb="http://www.stormware.cz/schema/version_2/addressbook.xsd" xmlns:prm="http://www.stormware.cz/schema/version_2/parameter.xsd" xmlns:lCon="http://www.stormware.cz/schema/version_2/list_contract.xsd" xmlns:ctg="http://www.stormware.cz/schema/version_2/category.xsd" xmlns:ipm="http://www.stormware.cz/schema/version_2/intParam.xsd">
<rsp:responsePackItem version="2.0" id="li1" state="ok">
<lst:listInvoice version="2.0" dateTimeStamp="2011-05-27T10:47:23Z" dateValidFrom="2011-05-27" state="ok">
<lst:invoice version="2.0">
<inv:invoiceHeader>
<inv:id>20</inv:id>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
<inv:number>
<typ:id>26</typ:id>
<typ:ids>1101</typ:ids>
<typ:numberRequested>110100001</typ:numberRequested>
</inv:number>
<inv:symVar>110100001</inv:symVar>
<inv:date>2011-01-30</inv:date>
<inv:dateTax>2011-01-30</inv:dateTax>
<inv:dateAccounting>2011-01-30</inv:dateAccounting>
<inv:dateDue>2011-02-13</inv:dateDue>
<inv:accounting>
<typ:id>17</typ:id>
<typ:ids>3Fv</typ:ids>
</inv:accounting>
<inv:classificationVAT>
<typ:id>251</typ:id>
<typ:ids>UD</typ:ids>
<typ:classificationVATType/>
</inv:classificationVAT>
<inv:text>Fakturujeme Vám zboží dle Vaší objednávky: </inv:text>
<inv:partnerIdentity>
<typ:id>15</typ:id>
<typ:address>
<typ:company>INTEAK spol. s r. o.</typ:company>
<typ:division>prodejna</typ:division>
<typ:name>David Jánský</typ:name>
<typ:city>Benešovice</typ:city>
<typ:street>Jiřího z Poděbrad 35</typ:street>
<typ:zip>463 48</typ:zip>
<typ:ico>85236972</typ:ico>
<typ:dic>CZ85236972</typ:dic>
</typ:address>
<typ:shipToAddress>
<typ:company/>
<typ:division/>
<typ:name/>
<typ:city/>
<typ:street/>
</typ:shipToAddress>
</inv:partnerIdentity>
<inv:myIdentity>
<typ:address>
<typ:company>Novák </typ:company>
<typ:surname>Novák</typ:surname>
<typ:name>Jan</typ:name>
<typ:city>Jihlava 1</typ:city>
<typ:street>Horní</typ:street>
<typ:number>15</typ:number>
<typ:zip>586 01</typ:zip>
<typ:ico>12345678</typ:ico>
<typ:dic>CZ12345678</typ:dic>
<typ:phone>569 876 542</typ:phone>
<typ:mobilPhone>602 852 369</typ:mobilPhone>
<typ:fax>564 563 216</typ:fax>
<typ:email>info#novak.cz</typ:email>
<typ:www>www.novak.cz</typ:www>
</typ:address>
</inv:myIdentity>
<inv:dateOrder>2011-01-22</inv:dateOrder>
<inv:paymentType>
<typ:id>1</typ:id>
<typ:ids>příkazem</typ:ids>
<typ:paymentType>draft</typ:paymentType>
</inv:paymentType>
<inv:account>
<typ:id>2</typ:id>
<typ:ids>KB</typ:ids>
</inv:account>
<inv:symConst>0308</inv:symConst>
<inv:centre>
<typ:id>1</typ:id>
<typ:ids>BRNO</typ:ids>
</inv:centre>
<inv:activity>
<typ:id>2</typ:id>
<typ:ids>NÁBYTEK</typ:ids>
</inv:activity>
<inv:liquidation>
<typ:date>2011-02-12</typ:date>
<typ:amountHome>356</typ:amountHome>
</inv:liquidation>
</inv:invoiceHeader>
<inv:invoiceDetail>
<inv:invoiceItem>
<inv:id>19</inv:id>
<inv:text>Židle Z220</inv:text>
<inv:quantity>2.0</inv:quantity>
<inv:unit>ks</inv:unit>
<inv:coefficient>1.0</inv:coefficient>
<inv:rateVAT>high</inv:rateVAT>
<inv:discountPercentage>0.0</inv:discountPercentage>
<inv:homeCurrency>
<typ:unitPrice>1968</typ:unitPrice>
<typ:price>3936</typ:price>
<typ:priceVAT>787.2</typ:priceVAT>
<typ:priceSum>4723.2</typ:priceSum>
</inv:homeCurrency>
<inv:code>Z220</inv:code>
<inv:guarantee>0</inv:guarantee>
<inv:guaranteeType>none</inv:guaranteeType>
<inv:stockItem>
<typ:store>
<typ:id>1</typ:id>
<typ:ids>ZBOŽÍ</typ:ids>
</typ:store>
<typ:stockItem>
<typ:id>27</typ:id>
<typ:ids>Z220</typ:ids>
<typ:PLU>650</typ:PLU>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
<inv:invoiceItem>
<inv:id>20</inv:id>
<inv:text>Konferenční stolek chrom</inv:text>
<inv:quantity>1.0</inv:quantity>
<inv:unit>ks</inv:unit>
<inv:coefficient>1.0</inv:coefficient>
<inv:rateVAT>high</inv:rateVAT>
<inv:discountPercentage>0.0</inv:discountPercentage>
<inv:homeCurrency>
<typ:unitPrice>7680</typ:unitPrice>
<typ:price>7680</typ:price>
<typ:priceVAT>1536</typ:priceVAT>
<typ:priceSum>9216</typ:priceSum>
</inv:homeCurrency>
<inv:note>Rozměr: 120 x 60</inv:note>
<inv:code>Konf11</inv:code>
<inv:guarantee>0</inv:guarantee>
<inv:guaranteeType>none</inv:guaranteeType>
<inv:stockItem>
<typ:store>
<typ:id>1</typ:id>
<typ:ids>ZBOŽÍ</typ:ids>
</typ:store>
<typ:stockItem>
<typ:id>10</typ:id>
<typ:ids>Konf11</typ:ids>
<typ:PLU>625</typ:PLU>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
<inv:invoiceItem>
<inv:id>21</inv:id>
<inv:text>Křeslo čalouněné 1320</inv:text>
<inv:quantity>4.0</inv:quantity>
<inv:unit>ks</inv:unit>
<inv:coefficient>1.0</inv:coefficient>
<inv:rateVAT>high</inv:rateVAT>
<inv:discountPercentage>0.0</inv:discountPercentage>
<inv:homeCurrency>
<typ:unitPrice>5988</typ:unitPrice>
<typ:price>23952</typ:price>
<typ:priceVAT>4790.4</typ:priceVAT>
<typ:priceSum>28742.4</typ:priceSum>
</inv:homeCurrency>
<inv:code>Kř1320</inv:code>
<inv:guarantee>0</inv:guarantee>
<inv:guaranteeType>none</inv:guaranteeType>
<inv:stockItem>
<typ:store>
<typ:id>1</typ:id>
<typ:ids>ZBOŽÍ</typ:ids>
</typ:store>
<typ:stockItem>
<typ:id>13</typ:id>
<typ:ids>Kř1320</typ:ids>
<typ:PLU>627</typ:PLU>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
</inv:invoiceDetail>
<inv:invoiceSummary>
<inv:roundingDocument>up2one</inv:roundingDocument>
<inv:roundingVAT>none</inv:roundingVAT>
<inv:homeCurrency>
<typ:priceNone>0</typ:priceNone>
<typ:priceLow>0</typ:priceLow>
<typ:priceLowVAT>0</typ:priceLowVAT>
<typ:priceLowSum>0</typ:priceLowSum>
<typ:priceHigh>35568</typ:priceHigh>
<typ:priceHighVAT>7113.6</typ:priceHighVAT>
<typ:priceHighSum>42681.6</typ:priceHighSum>
<typ:round>
<typ:priceRound>0.4</typ:priceRound>
</typ:round>
</inv:homeCurrency>
</inv:invoiceSummary>
</lst:invoice>
</lst:listInvoice>
</rsp:responsePackItem>
</rsp:responsePack>
Please, how can I get data such as: (?)
inv:invoiceSummary - typ:priceHighSum
inv:partnerIdentity - typ:name, typ:ico
inv:myIdentity - typ:company
inv:liquidation - typ:date
I tried this but can't get it working:
import xml.etree.ElementTree as ET
tree = ET.parse('temp_xml2.xml')
root = tree.getroot()
for listInvoice in root.findall('listInvoice'):
invoiceHeader = listInvoice.find('invoiceHeader').text
print invoiceHeader
Try yo use jsoup. An related example is parse XML.
this works:
for listInvoice in root.findall('.//{http://www.stormware.cz/schema/version_2/invoice.xsd}invoiceHeader'):
invoiceHeader = listInvoice.find('.//{http://www.stormware.cz/schema/version_2/invoice.xsd}id').text
print invoiceHeader

Categories