Skip to content
Python Basics: Round-Trip XML and Binary Property Lists

Python Basics: Round-Trip XML and Binary Property Lists

October 29, 2026

Apple property lists can be inspected on Linux with Python’s standard library. A small in-memory fixture shows how XML and binary encodings preserve the same supported values, and how an unsupported value fails before any file is written.

Prepare a scratch directory

Tested on Linux with CPython 3.12.14. You need Bash, Python, a text editor, and the standard mktemp, rm, and rmdir utilities. Run without -O so the assertions remain enabled. No external packages are required.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-plistlib.py:

import plistlib

settings = {
    "enabled": True,
    "name": "demo",
    "ports": [8080, 8443],
    "token": b"\x00\xff",
}
for label, format_code in [
    ("XML", plistlib.FMT_XML),
    ("binary", plistlib.FMT_BINARY),
]:
    encoded = plistlib.dumps(settings, fmt=format_code)
    restored = plistlib.loads(encoded)
    assert restored == settings
    assert isinstance(restored["token"], bytes)
    print(f"{label}: round trip matches")
    print("Token bytes:", restored["token"].hex())

try:
    plistlib.dumps({"optional": None})
except TypeError:
    print("None: unsupported value")
else:
    raise AssertionError("expected an unsupported-value error")

try:
    plistlib.dumps({42: "not a string key"})
except TypeError:
    print("Integer dictionary key: rejected")
else:
    raise AssertionError("expected a non-string-key error")

Run it:

python3 -B demonstrate-plistlib.py

Observed output:

XML: round trip matches
Token bytes: 00ff
binary: round trip matches
Token bytes: 00ff
None: unsupported value
Integer dictionary key: rejected

Read the result

dumps() produces bytes, and loads() detects the encoding for these generated inputs. The token remains binary data in both round trips; it is not decoded as text. XML is convenient for inspection, while binary property lists require a parser.

The two deliberate failures illustrate schema boundaries: property lists are not a serialization format for arbitrary Python objects. None and non-string dictionary keys do not fit this fixture’s property-list schema.

Apply it carefully

This example checks only small trusted values. Validate the expected keys and value types after loading an incoming document, and bound its size. Do not use skipkeys=True merely to silence invalid dictionary keys: that can silently lose data. Property lists are distinct from arbitrary XML and from Apple keyed archives, which require understanding their own object conventions.

The official plistlib reference describes the relevant APIs and their limits.

Clean up

Remove the saved source, return to the starting directory, and remove the empty practice directory:

rm -- demonstrate-plistlib.py
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on