cmeel-tinyxml2: Python Bindings for TinyXML-2
cmeel-tinyxml2 provides efficient Python bindings for TinyXML-2, a small, fast, and simple C++ XML parser. It allows Python developers to leverage the underlying C++ library's performance for parsing, creating, and manipulating XML documents directly from Python. The current version is 10.0.0, with releases typically aligning with upstream TinyXML-2 updates and the `cmeel` packaging cycle.
Common errors
-
ModuleNotFoundError: No module named 'tinyxml2'
cause The `cmeel-tinyxml2` package is either not installed, or the `import` statement uses an incorrect module name.fixEnsure the package is installed with `pip install cmeel-tinyxml2`. Verify that the import statement is `import tinyxml2`. -
Document has no root element. (or similar error via doc.ErrorStr())
cause The XML string or file being parsed is malformed, empty, or lacks a valid root element, causing TinyXML-2 to report a parsing error.fixInspect the XML input for correctness. After `doc.Parse()` or `doc.LoadFile()`, always check `if doc.Error():` and print `doc.ErrorStr()` to get the specific reason for the parsing failure. -
AttributeError: 'XMLElement' object has no attribute 'get_attribute'
cause The Python bindings expose the C++ API directly. The method names are often in C++ PascalCase (`SetAttribute`, `FirstChildElement`) rather than Python snake_case (`set_attribute`, `first_child_element`).fixConsult the quickstart or the `cmeel-tinyxml2` source/documentation for the correct PascalCase method names (e.g., `SetAttribute`, `Attribute`, `FirstChildElement`).
Warnings
- gotcha TinyXML-2 uses a C++-style error handling approach where methods return status codes or require explicit checks via `XMLDocument.Error()` or `XMLElement.Error()` after operations. Unlike Pythonic exceptions, you must explicitly check for errors, especially after parsing (`Parse`, `LoadFile`) or file operations (`SaveFile`).
- gotcha When loading or saving files using `LoadFile` and `SaveFile`, ensure the provided paths are valid and that your application has the necessary read/write permissions. File I/O errors will set the document's internal error state.
- breaking Upgrading `cmeel-tinyxml2` might implicitly upgrade the underlying TinyXML-2 C++ library. While `cmeel` aims for stable bindings, major version bumps in TinyXML-2 (or `cmeel-tinyxml2`) could introduce API changes or subtle behavioral differences that break existing code.
Install
-
pip install cmeel-tinyxml2
Imports
- tinyxml2
import tinyxml2
- XMLDocument
import tinyxml2 doc = tinyxml2.XMLDocument()
- XMLElement
import tinyxml2 elem = tinyxml2.XMLElement('tag')
Quickstart
import tinyxml2
import os
# Create a new document
doc = tinyxml2.XMLDocument()
# Add a declaration (optional but good practice)
doc.InsertEndChild(doc.NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""))
# Create a root element
root = doc.NewElement("Root")
doc.InsertEndChild(root)
# Add a child element with an attribute and text
child = doc.NewElement("Item")
child.SetAttribute("id", 123)
child.SetText("Example Text")
root.InsertEndChild(child)
# Add another child
another_child = doc.NewElement("SubItem")
another_child.SetText("More data")
child.InsertEndChild(another_child)
# Print the document to stdout
printer = tinyxml2.XMLPrinter()
doc.Print(printer)
print("\n--- Generated XML ---")
print(printer.CStr())
# Example of parsing an XML string
xml_string = "<data><item value='parsed_value'/></data>"
parsed_doc = tinyxml2.XMLDocument()
parsed_doc.Parse(xml_string)
print("\n--- Parsed XML Content ---")
if not parsed_doc.Error():
root_element = parsed_doc.FirstChildElement("data")
if root_element:
item_element = root_element.FirstChildElement("item")
if item_element:
print(f"Parsed item value: {item_element.Attribute('value')}")
else:
print("Item element not found.")
else:
print("Data root element not found.")
elif parsed_doc.ErrorID() == tinyxml2.XML_NO_ERROR:
print("Parsing completed with no document errors, but might be empty.")
else:
print(f"Parsing error: {parsed_doc.ErrorStr()} (ID: {parsed_doc.ErrorID()})")
# Example of saving to a file (optional, requires write access)
# output_filename = "output.xml"
# if os.environ.get('ENABLE_FILE_WRITE', '0') == '1': # Use env var for safety
# if doc.SaveFile(output_filename):
# print(f"XML successfully saved to {output_filename}")
# else:
# print(f"Error saving XML to {output_filename}: {doc.ErrorStr()}")