Python Basics: Round-Trip XML and Binary Property Lists
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 1Run 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.pyObserved output:
XML: round trip matches
Token bytes: 00ff
binary: round trip matches
Token bytes: 00ff
None: unsupported value
Integer dictionary key: rejectedRead 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_dirIf the directory is not empty, inspect its remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.