Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python XML findall does not work

Tags:

python

xml

I am trying to use findall to select on some xml elements, but i can't get any results.

import xml.etree.ElementTree as ET
import sys

storefront = sys.argv[1]

xmlFileName = 'promotions{0}.xml'

xmlFile = xmlFileName.format(storefront)

csvFileName = 'hrz{0}.csv'
csvFile = csvFileName.format(storefront)
ET.register_namespace('', "http://www.demandware.com/xml/impex/promotion/2008-01-31")
tree = ET.parse(xmlFile)

root = tree.getroot()
print('------------------Generate test-------------\n')



csv = open(csvFile,'w')
n = 0
for child in root.findall('campaign'):
    print(child.attrib['campaign-id'])
    print(n)
    n+=1

The XML looks something like this:

  <?xml version="1.0" encoding="UTF-8"?>
<promotions xmlns="http://www.demandware.com/xml/impex/promotion/2008-01-31">
    <campaign campaign-id="10off-310781">
        <enabled-flag>true</enabled-flag>
        <campaign-scope>
            <applicable-online/>
        </campaign-scope>
        <customer-groups match-mode="any">
            <customer-group group-id="Everyone"/>
        </customer-groups>
    </campaign>

    <campaign campaign-id="MNT-deals">
        <enabled-flag>true</enabled-flag>
        <campaign-scope>
            <applicable-online/>
        </campaign-scope>
        <start-date>2017-07-03T22:00:00.000Z</start-date>
        <end-date>2017-07-31T22:00:00.000Z</end-date>
        <customer-groups match-mode="any">
            <customer-group group-id="Everyone"/>
        </customer-groups>
    </campaign>

    <campaign campaign-id="black-friday">
        <enabled-flag>true</enabled-flag>
        <campaign-scope>
            <applicable-online/>
        </campaign-scope>
        <start-date>2017-11-23T23:00:00.000Z</start-date>
        <end-date>2017-11-24T23:00:00.000Z</end-date>
        <customer-groups match-mode="any">
            <customer-group group-id="Everyone"/>
        </customer-groups>
        <custom-attributes>
            <custom-attribute attribute-id="expires_date">2017-11-29</custom-attribute>
        </custom-attributes>
    </campaign>

    <promotion-campaign-assignment promotion-id="winter17-new-bubble" campaign-id="winter17-new-bubble">
        <qualifiers match-mode="any">
            <customer-groups/>
            <source-codes/>
            <coupons/>
        </qualifiers>
        <rank>100</rank>
    </promotion-campaign-assignment>

    <promotion-campaign-assignment promotion-id="xmas" campaign-id="xmas">
        <qualifiers match-mode="any">
            <customer-groups/>
            <source-codes/>
            <coupons/>
        </qualifiers>
    </promotion-campaign-assignment>

</promotions>

Any ideas what i am doing wrong? I have tried different solutions that i found on stackoverflow but nothing seems to work for me(from the things i have tried). The list is empty. Sorry if it is something very obvious i am new to python.

like image 446
Cosmin_Victor Avatar asked Aug 05 '26 01:08

Cosmin_Victor


1 Answers

As mentioned here by @MartijnPieters, etree's .findall uses the namespaces argument while the .register_namespace() is used for xml output of the tree. Therefore, consider mapping the default namespace with an explicit prefix. Below uses doc but can even be cosmin.

Additionally, consider with and enumerate() even the csv module as better handlers for your print and CSV outputs.

import csv
...

root = tree.getroot()
print('------------------Generate test-------------\n')

with open(csvFile, 'w') as f:
    c = csv.writer(f, lineterminator='\n')

    for n, child in enumerate(root.findall('doc:campaign', namespaces={'doc':'http://www.demandware.com/xml/impex/promotion/2008-01-31'})):
        print(child.attrib['campaign-id'])
        print(n)
        c.writerow([child.attrib['campaign-id']])

# ------------------Generate test-------------

# 10off-310781
# 0
# MNT-deals
# 1
# black-friday
# 2
like image 178
Parfait Avatar answered Aug 07 '26 19:08

Parfait