2
\$\begingroup\$

I want to retrieve id and name per skill. It works but is it well done? I would like to stay with minidom but all advices will be appreciated.

# This is only part of XML that interesting me:
# <skill>
#   <id>14</id>
#   <skill>
#     <name>C++</name>
#   </skill>
# </skill>
# <skill>
#   <id>15</id>
#   <skill>
#     <name>Java</name>
#   </skill>
# </skill>

skills = document.getElementsByTagName('skill')

for skill in skills:
    try:
        id_ = skill.getElementsByTagName('id')[0].firstChild.nodeValue
        name = skill.getElementsByTagName('name')[0].firstChild.nodeValue

        my_object.create(name=name.strip(),
                         id=id_.strip())
    except IndexError:
        pass
\$\endgroup\$
  • \$\begingroup\$ Your xml doesn't seem to match your code (and is also not well formed). \$\endgroup\$ – Francis Avila Apr 26 '13 at 21:27
2
\$\begingroup\$

This is probably as good as you can get with minidom.

However, consider ditching minidom--it's really only there when you absolutely, postively need some kind of DOM api and only have the standard library. Note the documentation for minidom.

Users who are not already proficient with the DOM should consider using the xml.etree.ElementTree module for their XML processing instead

Warning: The xml.dom.minidom module is not secure against maliciously constructed data. If you need to parse untrusted or unauthenticated data see XML vulnerabilities.

XML in Python is almost always processed with the ElementTree interface, not a DOM interface. There are many implementations of ElementTree including xml.etree.ElementTree (pure Python, in stdlib) and xml.etree.cElementTree (CPython, in stdlib), and lxml (third-party all-singing, all-dancing xml processing library that uses libxml2).

Here is how I would do this:

try:
    # On Python 2.x, use the faster C implementation if available
    from xml.etree import cElementTree as ET
except ImportError:
    # pure-python fallback
    # In Python3 just use this, not the one above:
    # Python3 will automatically choose the fastest implementation available.
    from xml.etree import ElementTree as ET

xmlstr = """<root>
<skill>
   <id>14</id>
   <name>C++</name>
 </skill>
 <skill>
   <id>15</id>
   <name>Java</name>
 </skill>
</root>"""

root = ET.fromstring(xmlstr)

def get_subelem_texts(elem, subelems):
    """Return {subelem: textval,...} or None if any subelems are missing (present but empty is ok)"""
    attrs = {}
    for sa in skillattrs:
        textval = skill.findtext(sa)
        if textval is None:
            return None
        attrs[sa] = textval.strip()
    return attrs


skillattrs = 'id name'.split()

for skill in root.find('skill'):
    args = get_subelem_texts(skill, skillattrs)
    if args is not None:
        my_object.create(**args)
\$\endgroup\$
0
\$\begingroup\$

In the sample code you provided, there are skill outer and inner tag names. The way you loop over them triggers to IndexError exceptions that you simply ignore.

Usually we handle exceptions in order to do something meaningful and concrete, not to ignore them. A way to avoid this dilemma is to simply avoid triggering those exceptions (especially that in practice you may have more elements than what you provided). So this is the way you could improve the code on this point:

>>> from xml.dom import minidom
>>> xml_string = '<top><skill><id>14</id><skill><name>C++</name></skill></skill><skill><id>15</id><skill><name>Java</name></skill></skill></top>'
>>> xml_dom = minidom.parseString(xml_string)
>>> ids = xml_dom.getElementsByTagName('id')
>>> names = xml_dom.getElementsByTagName('name')
>>> language_ids = [ids[i].firstChild.data for i in range(len(ids))]
>>> language_names = [names[i].firstChild.data for i in range(len(names))]
>>> language_ids_with_names = dict(zip(language_ids, language_names))
>>> language_ids_with_names
{u'15': u'Java', u'14': u'C++'}

Note that I added a root element called top for the XML string you provided, otherwise I can not parse it.

I do not see a reason why to change the library for this code. Many people ask to use minidom alternatives but there are many situations where minidom is effective and useful and I used it many times professionally.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.