Let me suggest two variations that I have used successfully in my day job (which is also my night job :).
1. For parsing .ini files, I wrote a wrapper around ConfigParser. The Python-level API looks like this (anonymized and idealized):
from XXX import MyConfigWrapper, optstr, optint, optbool, optfloat
class Config(MyConfigWrapper): poll_time = optfloat("network-parameters", "poll-time") use_ssl = optbool("network-parameters", "use-ssl") window_title = optstr("ui-parameters", "window-title") # etc.
This allows the Python names for variables to differ from the names used in the .ini file, and abstracts away the section names completely from the Python API. This makes it possible to rename variables and sections in the config file without having to touch the Python code that uses them. This will save my butt when our marketing team comes up with the *real* name for our product, since currently the section names all have the provisional product name in it, and the config file is considered "user-facing" so references to the old product name have to be expunged. Also, I don't see much point in having to use longer references in my Python code -- the total number of config parameters and their uses are such that I can easily come up with a single unique name for every option, and yet in the .ini file I'd like to have more than one section.
Note that optstr etc. construct full properties that allow me to set and delete the parameter values as well, and then ConfigParser can be told to write back the modified .ini file. This loses the ordering and comment, but I don't care (although I wish ConfigParser would order things alphabetically rather than per dictionary hash). I don't think I have to explain that optint returns a Python int, etc.
2. We're handling modest amounts of XML, all using home-grown DTDs and with no specific requirements to interface to other apps or XML tools. I wrote a metaclass which lets me specify the DTD using Python syntax. Again, my approach is slightly lower-level than previous proposals here but has the advantage of letting you be explicit about the mapping between Python and XML names, both for attributes and for subelements. The metaclass handles reading and writing. It supports elements containing text (is that CDATA? I never know) or sub-elements, but not both. For sub-elements, it supports cases where one element has any number of sub-elements of a certain type, which are then collected in a list, so you can refer to them using Python sequence indexing/slicing notation. It also supports elements that have zero or one sub-element of a certain type; absence is indicated by setting the corresponding attribute to None. I don't support namespaces, although I expect it would be easy enough to add them. I don't support unrecognized elements or attributes: while everything can be omitted (and defaults to None), unrecognized attributes or elements are always rejected. (I suppose that could be fixed too if desired.) Here's an example:
from XXX import ElementMetaClass, String, Integer, Float, Boolean, Date
class Inner(ElementMetaClass): "Definition for <inner>" __element__ = "inner" __attributes__ = [("count", Integer), ("name", String), ("expiration-date", Date), ("date-created", Date), ("special", Boolean)] __characters__ = "text" # CDATA (?) is stored as self.text
class Outer(ElementMetaClass): "Definition for <outer>" __element__ = "outer" __attributes__ = [("name", String)] __children__ = [("innerElements", Inner)]
Note that for attributes, the name given is used both as the Python name and as the XML name, except that hyphens in XML are translated into underscores in Python, and vice versa.
For sub-elements, the __element__ attribute of the class determines the element name, and the name given in the list of __children__ determines the Python name; if this ends in "" it is a repeatable element.
I'm undecided on whether I like the approach with lists of (name, type) tuples better than the approach with property factories like in the first example; the list approach allows me to order the attributes and sub-elements consistently upon rendering, but I'm not particularly keen on typing string quotes around Python identifiers.