🔍 Code Extractor

function _emit

Maturity: 38

Recursively converts a dictionary structure into XML SAX events, emitting them through a content handler for XML generation.

File:
/tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/xmltodict.py
Lines:
397 - 473
Complexity:
complex

Purpose

This function is the core recursive engine for converting Python dictionaries to XML format. It traverses nested dictionary structures and generates corresponding SAX events (startElement, characters, endElement) through a content handler. It handles attributes (prefixed with '@'), text content (using '#text' key), namespaces, pretty printing, and various XML formatting options. The function is designed to work with xmltodict-style dictionary representations where keys become XML elements and special keys denote attributes and text content.

Source Code

def _emit(key, value, content_handler,
          attr_prefix='@',
          cdata_key='#text',
          depth=0,
          preprocessor=None,
          pretty=False,
          newl='\n',
          indent='\t',
          namespace_separator=':',
          namespaces=None,
          full_document=True,
          expand_iter=None):
    key = _process_namespace(key, namespaces, namespace_separator, attr_prefix)
    if preprocessor is not None:
        result = preprocessor(key, value)
        if result is None:
            return
        key, value = result
    if (not hasattr(value, '__iter__')
            or isinstance(value, _basestring)
            or isinstance(value, dict)):
        value = [value]
    for index, v in enumerate(value):
        if full_document and depth == 0 and index > 0:
            raise ValueError('document with multiple roots')
        if v is None:
            v = _dict()
        elif isinstance(v, bool):
            if v:
                v = _unicode('true')
            else:
                v = _unicode('false')
        elif not isinstance(v, dict):
            if expand_iter and hasattr(v, '__iter__') and not isinstance(v, _basestring):
                v = _dict(((expand_iter, v),))
            else:
                v = _unicode(v)
        if isinstance(v, _basestring):
            v = _dict(((cdata_key, v),))
        cdata = None
        attrs = _dict()
        children = []
        for ik, iv in v.items():
            if ik == cdata_key:
                cdata = iv
                continue
            if ik.startswith(attr_prefix):
                ik = _process_namespace(ik, namespaces, namespace_separator,
                                        attr_prefix)
                if ik == '@xmlns' and isinstance(iv, dict):
                    for k, v in iv.items():
                        attr = 'xmlns{}'.format(':{}'.format(k) if k else '')
                        attrs[attr] = _unicode(v)
                    continue
                if not isinstance(iv, _unicode):
                    iv = _unicode(iv)
                attrs[ik[len(attr_prefix):]] = iv
                continue
            children.append((ik, iv))
        if pretty:
            content_handler.ignorableWhitespace(depth * indent)
        content_handler.startElement(key, AttributesImpl(attrs))
        if pretty and children:
            content_handler.ignorableWhitespace(newl)
        for child_key, child_value in children:
            _emit(child_key, child_value, content_handler,
                  attr_prefix, cdata_key, depth+1, preprocessor,
                  pretty, newl, indent, namespaces=namespaces,
                  namespace_separator=namespace_separator,
                  expand_iter=expand_iter)
        if cdata is not None:
            content_handler.characters(cdata)
        if pretty and children:
            content_handler.ignorableWhitespace(depth * indent)
        content_handler.endElement(key)
        if pretty and depth:
            content_handler.ignorableWhitespace(newl)

Parameters

Name Type Default Kind
key - - positional_or_keyword
value - - positional_or_keyword
content_handler - - positional_or_keyword
attr_prefix - '@' positional_or_keyword
cdata_key - '#text' positional_or_keyword
depth - 0 positional_or_keyword
preprocessor - None positional_or_keyword
pretty - False positional_or_keyword
newl - '\n' positional_or_keyword
indent - '\t' positional_or_keyword
namespace_separator - ':' positional_or_keyword
namespaces - None positional_or_keyword
full_document - True positional_or_keyword
expand_iter - None positional_or_keyword

Parameter Details

key: The XML element name/tag to emit. Will be processed for namespace handling.

value: The value associated with the key. Can be a string, dict, list, bool, None, or any iterable. Dictionaries represent nested elements, strings become text content, lists cause multiple elements with the same tag.

content_handler: An XML SAX ContentHandler instance (typically XMLGenerator) that receives the SAX events (startElement, endElement, characters, etc.).

attr_prefix: String prefix used to identify dictionary keys that should be treated as XML attributes. Default is '@', so '@id' becomes an attribute 'id'.

cdata_key: Dictionary key name used to identify character data (text content) within an element. Default is '#text'.

depth: Current recursion depth level, used for indentation in pretty printing. Starts at 0 for root element.

preprocessor: Optional callable that takes (key, value) and returns modified (key, value) tuple or None to skip emission. Used for custom transformations before XML generation.

pretty: Boolean flag to enable pretty printing with indentation and newlines. Default is False for compact output.

newl: String to use for newlines in pretty printing. Default is '\n'.

indent: String to use for one level of indentation in pretty printing. Default is '\t' (tab character).

namespace_separator: Character used to separate namespace prefix from local name. Default is ':'.

namespaces: Dictionary mapping namespace prefixes to URIs for namespace processing.

full_document: Boolean flag that enforces single root element constraint when True. Raises ValueError if multiple root elements detected at depth 0.

expand_iter: Optional string key name. If provided, iterables (except strings/dicts) will be wrapped in a dictionary with this key, creating a parent element.

Return Value

This function returns None. It operates by side-effect, emitting SAX events to the provided content_handler. The XML output is generated through the content handler's methods rather than being returned directly.

Dependencies

  • xml.sax.saxutils
  • xml.sax.xmlreader

Required Imports

from xml.sax.xmlreader import AttributesImpl

Usage Example

from xml.sax.saxutils import XMLGenerator
from xml.sax.xmlreader import AttributesImpl
from io import StringIO

# Define required helper types/functions (simplified)
_basestring = str
_unicode = str
_dict = dict

def _process_namespace(key, namespaces, separator, prefix):
    return key

# Create output buffer and content handler
output = StringIO()
handler = XMLGenerator(output, encoding='utf-8')

# Start document
handler.startDocument()

# Example dictionary to convert
data = {
    '@id': '123',
    '#text': 'Hello World',
    'child': {'@attr': 'value', '#text': 'Child text'}
}

# Emit XML
_emit('root', data, handler, attr_prefix='@', cdata_key='#text', depth=0, pretty=True)

# End document
handler.endDocument()

# Get XML string
xml_output = output.getvalue()
print(xml_output)

Best Practices

  • Always ensure the content_handler is properly initialized before calling this function
  • When full_document=True, ensure the value parameter represents a single root element to avoid ValueError
  • Use the preprocessor parameter for custom key/value transformations before XML emission
  • Be cautious with deeply nested structures as this is a recursive function that could hit Python's recursion limit
  • The attr_prefix and cdata_key conventions must be consistent with how the input dictionary was structured
  • For namespace support, provide a proper namespaces dictionary mapping prefixes to URIs
  • When pretty=True, be aware that whitespace will be added which may affect XML parsing in whitespace-sensitive contexts
  • Boolean values are converted to lowercase strings 'true' and 'false'
  • None values are converted to empty dictionaries, resulting in empty XML elements

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class _DictSAXHandler 70.6% similar

    A SAX (Simple API for XML) event handler that converts XML documents into Python dictionaries, with extensive configuration options for handling attributes, namespaces, CDATA, and structure.

    From: /tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/xmltodict.py
  • function unparse 65.1% similar

    Converts a Python dictionary into an XML document string, serving as the reverse operation of XML parsing. Supports customizable formatting, encoding, and XML generation options.

    From: /tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/xmltodict.py
  • function parse 59.1% similar

    Parses XML input (string, file-like object, or generator) and converts it into a Python dictionary representation with configurable options for attributes, namespaces, comments, and streaming.

    From: /tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/xmltodict.py
  • function _process_namespace 44.4% similar

    Processes XML namespace prefixes in element/attribute names by resolving them against a namespace dictionary and reconstructing the full qualified name.

    From: /tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/xmltodict.py
  • function xml_escape 40.1% similar

    Escapes special XML characters in a string by replacing them with their corresponding XML entity references.

    From: /tf/active/vicechatdev/SPFCsync/venv/lib64/python3.11/site-packages/office365/runtime/auth/providers/saml_token_provider.py
← Back to Browse