Cosmin_Victor
Cosmin_Victor

Reputation: 154

Python XML findall does not work

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.

Upvotes: 3

Views: 2892

Answers (1)

Parfait
Parfait

Reputation: 107587

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

Upvotes: 3

Related Questions