xmltodict Documentation

repository·master·Indexed 27 days ago

https://github.com/martinblech/xmltodict

A Python module that allows developers to work with XML data as if it were JSON, providing easy conversion between XML and Python dictionaries. It includes functions for parsing XML into dictionaries via xmltodict.parse() and converting dictionaries back to XML via xmltodict.unparse(), with support for namespaces, streaming mode for large files, CDATA wrapping, and forced list values.

Tokens
2.5K
Snippets
8
Records
11
Agent score
41%

What's inside xmltodict

  1. Use streaming mode for large XML files

    master

    For very large XML files, use the streaming mode to maintain a small memory footprint. You can specify an item_depth and an item_callback function that is called whenever an element at that depth is reached.

    from gzip import GzipFile
    import xmltodict
    
    def handle_artist(_, artist):
        print(artist['name'])
        return True
    
    # Parse a large gzipped XML file item by item
    xmltodict.parse(GzipFile('discogs_artists.xml.gz'),
                    item_depth=2, 
                    item_callback=handle_artist)
  2. Install xmltodict

    master

    You can install xmltodict using various package managers depending on your environment:

    • PyPI: pip install xmltodict
    • Conda: conda install -c conda-forge xmltodict
    • Fedora/RHEL: sudo yum install python3-xmltodict
    • Arch Linux: sudo pacman -S python-xmltodict
    • Debian/Ubuntu: sudo apt install python-xmltodict
    • FreeBSD: pkg install py36-xmltodict
    • openSUSE/SLE: zypper in python3-xmltodict (for Python 3) or zypper in python2-xmltodict (for Python 2)
    $ pip install xmltodict
  3. Install type annotations for xmltodict

    master

    To enable type checking support for xmltodict, install the external types package via PyPI or Conda:

    • PyPI: pip install types-xmltodict
    • Conda: conda install -c conda-forge types-xmltodict
    $ pip install types-xmltodict
  4. Force CDATA wrapping for specific elements

    master

    The force_cdata parameter in xmltodict.parse() allows you to wrap text content in CDATA sections. You can pass:

    • A boolean (True to force all, False for none).
    • A tuple of element names to force CDATA for specific tags.
    • A callable function that accepts (path, key, value) and returns a boolean.
    import xmltodict
    
    xml = '<a><b>data1</b><c>data2</c><d>data3</d></a>'
    
    # Force CDATA only for 'b' and 'd' elements
    parsed = xmltodict.parse(xml, force_cdata=('b', 'd'))
    
    # Use a callable for complex logic
    def should_force_cdata(path, key, value):
        return key in ['b', 'd'] and len(value) > 4
    
    parsed_complex = xmltodict.parse(xml, force_cdata=should_force_cdata)
  5. Handle XML namespaces in xmltodict.parse()

    master

    By default, xmltodict treats namespace declarations as regular attributes. To expand namespaces, set process_namespaces=True. You can also use the namespaces argument to map specific URIs to shorthand prefixes or set a URI to None to skip it entirely.

    xml = """
    <root xmlns="http://defaultns.com/"
          xmlns:a="http://a.com/"
          xmlns:b="http://b.com/">
      <x>1</x>
      <a:y>2</a:y>
      <b:z>3</b:z>
    </root>
    """
    
    # Expand namespaces
    parsed = xmltodict.parse(xml, process_namespaces=True)
    
    # Collapse or skip namespaces using a mapping
    namespaces = {
        'http://defaultns.com/': None, # skip
        'http://a.com/': 'ns_a',      # collapse to 'ns_a'
    }
    parsed_custom = xmltodict.parse(xml, process_namespaces=True, namespaces=namespaces)
  6. Parse XML into a Python dictionary with xmltodict.parse()

    master

    Use xmltodict.parse() to convert XML strings or file-like objects into Python dictionaries. This makes XML manipulation feel like working with JSON. By default, attributes are prefixed with @ and text content uses the #text key.

    import xmltodict
    import json
    
    xml_data = """
     <mydocument has="an attribute">
       <and>
         <many>elements</many>
         <many>more elements</many>
       </and>
       <plus a="complex">
         element as well
       </plus>
     </mydocument>
     """
    
    parsed_dict = xmltodict.parse(xml_data)
    print(json.dumps(parsed_dict, indent=4))
  7. Force list values for specific elements

    master

    The force_list parameter in xmltodict.parse() ensures that certain elements are always returned as lists, even if they only contain a single item. This is useful for maintaining consistent data structures. You can pass:

    • A boolean (True to force all, False for none).
    • A tuple of element names to force lists for specific tags.
    • A callable function that accepts (path, key, value) and returns a boolean.
    import xmltodict
    
    xml = '<a><b>data1</b><b>data2</b><c>data3</c></a>'
    
    # Force lists only for 'b' elements
    parsed = xmltodict.parse(xml, force_list=('b',))
    
    # Use a callable for complex logic
    def should_force_list(path, key, value):
        return key in ['b'] and isinstance(value, str)
    
    parsed_complex = xmltodict.parse(xml, force_list=should_force_list)
  8. Use expand_iter to provide tags for nested lists during unparse

    master

    When converting nested lists to XML, if a list does not have a parent key to use as a tag, xmltodict converts items to strings. To provide explicit tags for these nested items, use the expand_iter argument in unparse().

    Warning: Using expand_iter breaks the ability to roundtrip the data back to the same format.

    import xmltodict
    
    # Nested list without a specific tag for items
    mydict = {
        "line": {
            "points": [
                [1, 5],
                [2, 6],
            ]
        }
    }
    
    # Standard unparse (converts inner lists to strings)
    print(xmltodict.unparse(mydict, pretty=True))
    
    # Using expand_iter to provide a tag for the inner items
    print(xmltodict.unparse(mydict, pretty=True, expand_iter="coord"))
  9. Convert a Python dictionary to XML with xmltodict.unparse()

    master

    Use xmltodict.unparse() to convert a dictionary back into an XML string.

    • Use the attr_prefix (default @) to define attributes.
    • Use the cdata_key (default #text) to define text content.
    • Use pretty=True for indented, readable output.
    • Note: Empty lists in a dictionary (e.g., {'a': []}) are skipped in the output. To produce an empty element, use a placeholder like {'a': ['']}.
  10. Reference: xmltodict.parse() arguments

    master

    Detailed list of arguments for xmltodict.parse():

    • xml_input: XML input as a string, file-like object, or generator of strings.
    • encoding=None: Character encoding for the input XML.
    • expat=expat: XML parser module to use.
    • process_namespaces=False: Expand XML namespaces if True.
    • namespace_separator=':': Separator between namespace URI and local name.
    • disable_entities=True: Disable entity parsing for security.
    • process_comments=False: Include XML comments if True.
    • xml_attribs=True: Include attributes in output dict (with attr_prefix).
    • attr_prefix='@': Prefix for XML attributes in the dict.
    • cdata_key='#text': Key for text content in the dict.
    • force_cdata=False: Force text content to be wrapped as CDATA for specific elements. Can be a boolean, a tuple of element names, or a callable (path, key, value) -> bool.
    • cdata_separator='': Separator string to join multiple text nodes.
    • postprocessor=None: Function to modify parsed items.
    • dict_constructor=dict: Constructor for dictionaries.
    • strip_whitespace=True: Remove leading/trailing whitespace in text nodes.
    • namespaces=None: Mapping of namespaces to prefixes.
    • force_list=None: Force list values for specific elements. Can be a boolean, a tuple of element names, or a callable (path, key, value) -> bool.
    • item_depth=0: Depth at which to call item_callback.
    • item_callback=lambda *args: True: Function called on items at item_depth.
    • comment_key='#comment': Key used for XML comments when process_comments=True.
  11. Reference: xmltodict.unparse() arguments

    master

    Detailed list of arguments for xmltodict.unparse():

    • input_dict: Dictionary to convert to XML.
    • output=None: File-like object to write XML to; returns string if None.
    • encoding='utf-8': Encoding of the output XML.
    • bytes_errors='replace': Error handler used when decoding byte values.
    • full_document=True: Include XML declaration if True.
    • short_empty_elements=False: Use short tags for empty elements (<tag/>).
    • attr_prefix='@': Prefix for dictionary keys representing attributes.
    • cdata_key='#text': Key for text content in the dictionary.
    • pretty=False: Pretty-print the XML output.
    • indent=' ': Indentation string for pretty printing.
    • newl=' ': Newline character for pretty printing.
    • expand_iter=None: Tag name to use for items in nested lists (breaks roundtripping).