### Install Pyuppsala Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Install the pyuppsala package using pip or uv. Python 3.10+ is required. ```bash python3 -m pip install pyuppsala ``` ```bash uv add pyuppsala ``` -------------------------------- ### Install Pyuppsala with uv Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Install the pyuppsala package using uv. Ensure you have Python 3.10 or later. ```bash uv add pyuppsala ``` -------------------------------- ### Clone and Set Up Pyuppsala Repository Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Clone the repository and synchronize dependencies using uv. This is the initial setup for development. ```bash # Clone the repository git clone https://github.com/kushaldas/pyuppsala.git cd pyuppsala # Set up the environment with uv uv sync ``` -------------------------------- ### Quick Start: Parse and Build XML Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/etree.md Demonstrates basic XML parsing and building using pyuppsala.etree. Includes element finding, attribute retrieval, and string conversion. ```python from pyuppsala import etree as ET # Parse root = ET.fromstring("Dune") book = root.find("book") assert book.text == "Dune" assert book.get("id") == "1" # Build cat = ET.Element("catalog") b = ET.SubElement(cat, "book", {"id": "2"}) b.text = "Neuromancer" print(ET.tostring(cat, encoding="unicode")) # Neuromancer ``` -------------------------------- ### XmlWriter.start_element(name, attrs=None) Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Starts an XML element, optionally with attributes. Raises ValueError for invalid names. ```APIDOC ## start_element(name, attrs=None) ### Description Start an element. `attrs` is an optional list of `(name, value)` tuples. Raises `ValueError` if `name` or any attribute name is not a valid XML name. ### Method `start_element(name, attrs=None)` ### Parameters - **name** (str) - The name of the element. - **attrs** (list[tuple[str, str]] | None) - Optional - A list of (name, value) tuples for attributes. ### Example ```python w = XmlWriter() w.start_element("div", [("class", "container"), ("id", "main")]) w.text("content") w.end_element("div") print(w.to_string()) # '
content
' ``` ### Returns `None` ``` -------------------------------- ### Install Pyuppsala with pip Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Install the pyuppsala package using pip. Ensure you have Python 3.10 or later. ```bash pip install pyuppsala ``` -------------------------------- ### Start XML Element with Attributes Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Begin an XML element and include attributes using a list of (name, value) tuples. Ensure element and attribute names are valid XML names. ```python w = XmlWriter() w.start_element("div", [("class", "container"), ("id", "main")]) w.text("content") w.end_element("div") print(w.to_string()) ``` -------------------------------- ### Create Basic XML with XmlWriter Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use XmlWriter to programmatically build an XML string. This includes writing the XML declaration, starting and ending elements, and adding text content. ```python from pyuppsala import XmlWriter w = XmlWriter() w.write_declaration() w.start_element("root") w.text("hello") w.end_element("root") print(w.to_string()) ``` -------------------------------- ### Node Protocols: Child Count, Iteration, and Indexing Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Demonstrates the use of Python protocols for Node objects, including getting the number of children, iterating over children, and accessing children by index. ```python doc = Document("") root = doc.document_element print(len(root)) # 3 print(root[0].tag.local_name) # "a" print(root[-1].tag.local_name) # "c" for child in root: print(child.tag.local_name, end=" ") # a b c ``` -------------------------------- ### Get Elements by Tag Name and Namespace Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use `get_elements_by_tag_name_ns` to find elements matching a specific namespace URI and local tag name. ```python doc = Document('') items = doc.get_elements_by_tag_name_ns("urn:ex", "item") print(len(items)) # 2 ``` -------------------------------- ### Get XML as String or Bytes Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Retrieve the constructed XML document as a string using `to_string()` or as bytes using `to_bytes()`. The `to_bytes()` method is useful for binary output requirements. ```python w = XmlWriter() w.start_element("root") w.end_element("root") data = w.to_bytes() print(type(data)) # ``` -------------------------------- ### Get Element Tag Information Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Retrieves tag name, namespace URI, prefix, and prefixed name for element nodes. ```python doc = Document('') root = doc.document_element print(root.tag.local_name) # "root" print(root.tag.namespace_uri) # "urn:ex" print(root.tag.prefix) # "ns" print(root.tag.prefixed_name) # "ns:root" ``` -------------------------------- ### Get Node Kind Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Demonstrates how to retrieve the 'kind' property for different node types within a document. ```python doc = Document("text") root = doc.document_element print(root.kind) # "element" print(root.children[0].kind) # "text" print(root.children[1].kind) # "comment" ``` -------------------------------- ### Find Child Elements by Namespace Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Use `first_child_element_by_name_ns()` to get the first matching child element by namespace URI and local name. Use `child_elements_by_name_ns()` to retrieve all matching child elements. ```python from pyuppsala import Document xml = """ first skip second """ doc = Document(xml) root = doc.document_element # Get the first matching child first = root.first_child_element_by_name_ns("urn:example", "item") print(first.element_text) # "first" # Get all matching children items = root.child_elements_by_name_ns("urn:example", "item") print(len(items)) # 2 ``` -------------------------------- ### Combine XmlWriter with XsdValidator Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Generate XML using `XmlWriter` and validate it against an XSD schema using `XsdValidator`. This example demonstrates creating an order with items and validating the structure and attributes. ```python from pyuppsala import XmlWriter, XsdValidator, parse # Define a schema schema = """ """ validator = XsdValidator(schema) # Build XML with XmlWriter w = XmlWriter() w.start_element("order", [("id", "42")]) w.start_element("item", [("qty", "3")]) w.text("Widget") w.end_element("item") w.start_element("item", [("qty", "1")]) w.text("Gadget") w.end_element("item") w.end_element("order") # Validate the generated XML xml = w.to_string() print(f"Valid: {validator.is_valid_str(xml)}") # True # Parse and inspect doc = parse(xml) for item in doc.get_elements_by_tag_name("item"): print(f" {item.element_text} x{item.get_attribute('qty')}") # Widget x3 # Gadget x1 ``` -------------------------------- ### Get Node Source Byte Range Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Uses 'source_range' to get the start and end byte offsets of a node within the original source string. Returns None for programmatically created nodes. ```python xml = "text" doc = Document(xml) child = doc.document_element.children[0] start, end = child.source_range print(xml[start:end]) # "text" ``` -------------------------------- ### Initialize and Access QName Attributes Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Demonstrates how to create QName objects with and without a namespace, and access their local name, prefixed name, and namespace URI. ```python from pyuppsala import QName # Local name only q = QName("root") print(q.local_name) # "root" # With namespace q = QName("item", namespace_uri="urn:example", prefix="ex") print(q.prefixed_name) # "ex:item" print(q.namespace_uri) # "urn:example" ``` -------------------------------- ### QName Constructor and Attributes Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Demonstrates how to create a QName object and access its attributes like local_name, namespace_uri, prefix, and prefixed_name. ```APIDOC ## class QName(local_name, namespace_uri=None, prefix=None) ### Description A qualified XML name. ### Parameters #### Constructor Parameters - **local_name** (str) - The local name of the XML element. - **namespace_uri** (str | None) - Optional. The namespace URI for the qualified name. - **prefix** (str | None) - Optional. The prefix associated with the namespace. #### Attributes - **local_name** (str) - The local part of the qualified name. - **namespace_uri** (str | None) - The namespace URI. - **prefix** (str | None) - The namespace prefix. - **prefixed_name** (str) - The prefixed form of the name (e.g., "ns:item") or just the local name. ### Request Example ```python from pyuppsala import QName # Local name only q = QName("root") print(q.local_name) # "root" # With namespace q = QName("item", namespace_uri="urn:example", prefix="ex") print(q.prefixed_name) # "ex:item" print(q.namespace_uri) # "urn:example" ``` ``` -------------------------------- ### Get Parent Node Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Accesses the 'parent' property to get the parent node of a given node. The document root has no parent. ```python doc = Document("") child = doc.document_element.children[0] print(child.parent.tag.local_name) # "root" ``` -------------------------------- ### Get First Text Child's Content Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Uses 'element_text' to quickly get the text of the first Text or CDATA child, without recursing. Useful for simple elements. ```python doc = Document("AliceA bold person") root = doc.document_element name = root.children[0] bio = root.children[1] print(name.element_text) # "Alice" print(bio.element_text) # "A " (only first text child, not recursive) print(bio.text_content) # "A bold person" (recursive) ``` -------------------------------- ### Get Recursively Collected Text Content Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Retrieves the 'text_content' property, which aggregates text from the node and all its descendants. ```python doc = Document("

Hello world!

") print(doc.document_element.text_content) # "Hello world!" ``` -------------------------------- ### Initializing XPathEvaluator Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Prepare a Document for XPath queries and initialize an XPathEvaluator. The Document must have prepare_xpath() called. ```python from pyuppsala import Document, XPathEvaluator doc = Document("
123") doc.prepare_xpath() xpath = XPathEvaluator() ``` -------------------------------- ### Using the lxml-compatible etree API Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Leverage the `pyuppsala.etree` submodule for an API compatible with `lxml.etree`. This allows for easier migration of existing lxml code. ```python from pyuppsala import etree root = etree.fromstring("hitail") print(root.find("b").text) # hi print(root.find("b").tail) # tail child = etree.SubElement(root, "c") child.text = "y" print(etree.tostring(root, encoding="unicode")) ``` -------------------------------- ### QName.matches Method Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Explains how to use the matches method to check if a QName object corresponds to a given local name and namespace URI, ignoring the prefix. ```APIDOC ## QName.matches(local_name: str, namespace_uri: str | None = None) → bool ### Description Check whether this QName matches the given local name and optional namespace URI. Prefix is ignored. ### Parameters #### Method Parameters - **local_name** (str) - The local name to compare against. - **namespace_uri** (str | None) - Optional. The namespace URI to compare against. ### Request Example ```python from pyuppsala import QName q = QName("item", namespace_uri="urn:example", prefix="ex") print(q.matches("item", namespace_uri="urn:example")) # True print(q.matches("item", namespace_uri="urn:other")) # False print(q.matches("item")) # False (namespace mismatch) print(q.matches("other", namespace_uri="urn:example")) # False # QName without namespace q2 = QName("root") print(q2.matches("root")) # True print(q2.matches("root", namespace_uri="urn:example")) # False ``` ### Response #### Success Response - **bool** - True if the QName matches the provided local name and namespace URI, False otherwise. ``` -------------------------------- ### Configure Resource Limits for XML Parsing Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Demonstrates how to inspect and adjust resource limits for XML parsing, XPath evaluation, and regex matching to prevent denial-of-service attacks. Default limits are safe for most use cases. ```python import pyuppsala from pyuppsala import parse, XPathEvaluator, XsdRegex, XmlParseError # Inspect the active defaults print(pyuppsala.DEFAULT_MAX_DEPTH) # 128 print(pyuppsala.DEFAULT_MAX_ENTITY_EXPANSION) # 1048576 print(pyuppsala.DEFAULT_MAX_XPATH_DEPTH) # 32 print(pyuppsala.DEFAULT_MAX_REGEX_GROUP_DEPTH) # 64 print(pyuppsala.DEFAULT_MAX_REGEX_STEPS) # 1000000 # Billion-laughs is rejected by default: each entity expands the next # tenfold, so &g; would expand to ~10 MiB -- well past the 1 MiB cap. billion_laughs = ( '' ' ' ' ' ' ' ']>' '&g;' ) try: parse(billion_laughs) except XmlParseError as e: print("blocked:", e) # Entity expansion exceeds configured limit # Raise the depth cap when a legitimate document needs it deep = "" * 200 + "" * 200 doc = parse(deep, max_depth=300) # Tighten the regex backtracking budget for an untrusted pattern rx = XsdRegex("(a|aa)+b") print(rx.is_match("a" * 30, max_steps=100)) # False -- bailed early # Raise the XPath depth cap for an unusually nested expression ev = XPathEvaluator(max_depth=128) ``` -------------------------------- ### Get Elements by Tag Name Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use `get_elements_by_tag_name` to find all elements with a specific local tag name within the document. ```python doc = Document("") elements = doc.get_elements_by_tag_name("a") print(len(elements)) # 2 ``` -------------------------------- ### Match QNames with Local Name and Namespace URI Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Shows how to use the `matches` method to compare a QName object against a local name and an optional namespace URI. The prefix is ignored during matching. ```python from pyuppsala import QName q = QName("item", namespace_uri="urn:example", prefix="ex") print(q.matches("item", namespace_uri="urn:example")) # True print(q.matches("item", namespace_uri="urn:other")) # False print(q.matches("item")) # False (namespace mismatch) print(q.matches("other", namespace_uri="urn:example")) # False # QName without namespace q2 = QName("root") print(q2.matches("root")) # True print(q2.matches("root", namespace_uri="urn:example")) # False ``` -------------------------------- ### Get Node Line and Column Numbers Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Retrieves the 'line' and 'column' properties to find the position of a node in the original source text. ```python xml = "\n \n" doc = Document(xml) child = doc.document_element.children[0] print(f"line {child.line}, column {child.column}") # line 2, column 3 ``` -------------------------------- ### Building an XML Document from Scratch Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Use `Document.empty()` to create a new document and `create_element()`, `create_text()`, and `append_child()` to construct the XML structure programmatically. This is useful for generating XML dynamically based on data. ```python from pyuppsala import Document doc = Document.empty() root = doc.create_element("catalog") doc.append_child(doc.root, root) products = [ {"id": "1", "name": "Widget", "price": "9.99"}, {"id": "2", "name": "Gadget", "price": "19.99"}, {"id": "3", "name": "Doohickey", "price": "4.99"}, ] for prod in products: elem = doc.create_element("product") elem.set_attribute("id", prod["id"]) name = doc.create_element("name") doc.append_child(name, doc.create_text(prod["name"])) doc.append_child(elem, name) price = doc.create_element("price") doc.append_child(price, doc.create_text(prod["price"])) doc.append_child(elem, price) doc.append_child(root, elem) print(doc.to_xml_with_options(indent=" ")) # # # Widget # 9.99 # # # Gadget # 19.99 # # # Doohickey # 4.99 # # ``` -------------------------------- ### Get Original Source Text of a Node Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Retrieves the 'source' property, which is the original text of the node. Returns None for programmatically created nodes. ```python xml = 'hello' doc = Document(xml) item = doc.document_element.children[0] print(item.source) # 'hello' # Programmatically created nodes have no source new_elem = doc.create_element("new") print(new_elem.source) # None ``` -------------------------------- ### Get Text Content of Text/Comment/CDATA Nodes Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Accesses the 'text' property for text, comment, and CDATA nodes. Returns None for element nodes. ```python doc = Document("hello") text_node = doc.document_element.children[0] print(text_node.text) # "hello" print(doc.document_element.text) # None (element, not text) ``` -------------------------------- ### Initialize XsdRegex for Email Pattern Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Instantiate XsdRegex with an email-like pattern. Use this to validate if a string conforms to a typical email format. The pattern is implicitly anchored to match the entire input. ```python from pyuppsala import XsdRegex # Email-like pattern email = XsdRegex(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}") print(email.is_match("user@example.com")) # True print(email.is_match("not-an-email")) # False ``` -------------------------------- ### QName Equality and Hashing Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Illustrates that equality for QNames is determined by local_name and namespace_uri, and that QNames are hashable, allowing their use in sets and as dictionary keys. ```APIDOC ## QName Equality and Hashing ### Description Equality is determined by `local_name` and `namespace_uri` (prefix is ignored). QNames are hashable. ### Request Example ```python from pyuppsala import QName # Same namespace, different prefix -- equal a = QName("item", namespace_uri="urn:ex", prefix="a") b = QName("item", namespace_uri="urn:ex", prefix="b") print(a == b) # True # Can be used in sets and as dict keys names = {a, b} print(len(names)) # 1 ``` ``` -------------------------------- ### Detach Node Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Detaches a node from its parent without destroying the node. The detached node can be re-attached later. This example shows detaching and re-attaching. ```python doc = Document("") root = doc.document_element b = root.children[1] doc.detach(b) print(len(root.children)) # 2 # Re-attach at the end doc.append_child(root, b) print(doc.to_xml()) # "" ``` -------------------------------- ### Namespaces with Clark Notation Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/etree.md Shows how to handle XML namespaces using Clark notation and the `nsmap` argument when creating elements. This is useful for defining elements within specific XML namespaces. ```python from pyuppsala import etree as ET # Namespaces (Clark notation) ns = ET.Element("{http://example.com/ns}root", nsmap={"e": "http://example.com/ns"}) ET.SubElement(ns, "{http://example.com/ns}item") print(ET.tostring(ns, encoding="unicode")) # ``` -------------------------------- ### Get Attribute Value by Name Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Uses 'get_attribute' to retrieve an attribute's value by its local name. Optionally filter by namespace URI. Returns None if the attribute is not found. ```python doc = Document('') item = doc.document_element print(item.get_attribute("id")) # "42" # With namespace print(item.get_attribute("lang", namespace_uri="http://www.w3.org/XML/1998/namespace")) # "en" # Missing attribute print(item.get_attribute("missing")) # None ``` -------------------------------- ### Build Release Wheel for Pyuppsala Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Build a release-ready wheel for the Pyuppsala project using maturin. This is typically done before publishing. ```bash # Build a release wheel uv run maturin build --release ``` -------------------------------- ### Utilize lxml-compatible etree API Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Replace `lxml.etree` imports with `pyuppsala.etree` to leverage Uppsala's XML processing capabilities with a familiar API. Supports common etree functions like `fromstring`, `Element`, `SubElement`, `tostring`, and element attribute/text access. ```python from pyuppsala import etree # instead of: from lxml import etree root = etree.fromstring("Dune") print(root.find("book").text) # Dune print(root[0].get("id")) # 1 cat = etree.Element("catalog") book = etree.SubElement(cat, "book", {"id": "2"}) book.text = "Neuromancer" print(etree.tostring(cat, encoding="unicode")) # Neuromancer ``` -------------------------------- ### Check XmlWriter State Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Determine if any content has been written to the `XmlWriter` using `bool(writer)` and get the number of bytes written using `len(writer)`. `str(writer)` is an alias for `to_string()`. ```python w = XmlWriter() print(bool(w)) # False print(len(w)) # 0 w.start_element("root") w.end_element("root") print(bool(w)) # True print(len(w)) # 13 ``` -------------------------------- ### Create Empty Document Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use the static `empty` method to create a new, empty document. Elements can then be created and appended to it. ```python doc = Document.empty() root = doc.create_element("root") doc.append_child(doc.root, root) print(doc.to_xml()) # "" ``` -------------------------------- ### Streaming XML Serialization Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Shows how to serialize XML documents to files, including pretty-printing, and how to serialize specific subtrees. This is useful for handling large XML files efficiently. ```python from pyuppsala import Document doc = Document("") # Write to a file doc.write_to_file("/tmp/output.xml") # Pretty-print to a file pretty = doc.to_xml_with_options(indent=" ") with open("/tmp/pretty.xml", "w") as f: f.write(pretty) # Serialize a subtree a_node = doc.get_elements_by_tag_name("a")[0] print(a_node.to_xml()) # "" ``` -------------------------------- ### XsdRegex Class Initialization Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Initialize an XsdRegex object with a pattern string. Optionally, set the maximum group-nesting depth. ```APIDOC ## XsdRegex(pattern, max_depth=None) ### Description Initializes an XSD regular expression pattern matcher. XSD regexes are implicitly anchored and must match the entire input string. ### Parameters * **pattern** (str) - The XSD regex pattern string. * **max_depth** (int, optional) - Maximum group-nesting depth applied at compile time. Defaults to `DEFAULT_MAX_REGEX_GROUP_DEPTH`. ### Raises * **ValueError** - If the pattern is invalid. ### Example ```python from pyuppsala import XsdRegex # Email-like pattern email = XsdRegex(r"[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}") print(email.is_match("user@example.com")) # True print(email.is_match("not-an-email")) # False ``` ``` -------------------------------- ### Build Native Extension in Development Mode Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Build the native extension in development mode using maturin. This command is used for active development and debugging. ```bash # Build the native extension in development mode uv run maturin develop ``` -------------------------------- ### Initialize XsdValidator with Schema String Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Create an XsdValidator instance by providing the XSD schema as an XML string. This is useful when the schema is readily available in memory. ```python from pyuppsala import XsdValidator schema = """ """ validator = XsdValidator(schema) ``` -------------------------------- ### Build XML with XmlWriter Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Construct XML documents programmatically using the XmlWriter. This is useful for creating output without needing to build a DOM first. ```python from pyuppsala import XmlWriter w = XmlWriter() w.write_declaration() w.start_element("catalog", [("xmlns", "urn:example")]) w.start_element("item", [("id", "1")]) w.text("Widget") w.end_element("item") w.end_element("catalog") print(w.to_string()) ``` -------------------------------- ### Import lxml.etree Alternative Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/etree.md Swap lxml.etree import with pyuppsala.etree to use the secure Rust parser. This code demonstrates basic parsing and element access. ```python from pyuppsala import etree root = etree.fromstring("hello") print(root.find("b").text) # hello ``` -------------------------------- ### QName Matching Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Use the QName class to represent and match XML qualified names, including their local names and namespace URIs. This is essential for precise XML element and attribute identification. ```python from pyuppsala import QName q = QName("Envelope", namespace_uri="http://schemas.xmlsoap.org/soap/envelope/", prefix="soap") # Match by local name and namespace print(q.matches("Envelope", namespace_uri="http://schemas.xmlsoap.org/soap/envelope/")) # True print(q.matches("Envelope")) # False -- namespace doesn't match None print(q.matches("Body", namespace_uri="http://schemas.xmlsoap.org/soap/envelope/")) # False ``` -------------------------------- ### Serialize to Compact XML Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes the entire document into a compact XML string. Whitespace is preserved as parsed. ```python doc = Document(" ") print(doc.to_xml()) # " " ``` -------------------------------- ### Secure Parsing with XMLParser Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/etree.md Illustrates how to configure security limits for XML parsing using `ET.XMLParser`. Use `huge_tree=True` to lift default caps or specify `max_depth` and `remove_comments`. ```python from pyuppsala import etree as ET parser = ET.XMLParser(huge_tree=True) # lift depth/expansion caps parser = ET.XMLParser(max_depth=256, remove_comments=True) root = ET.fromstring(deeply_nested_xml, parser) ``` -------------------------------- ### Serialize with Formatting Options Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes the document with customizable formatting options, including indentation, expansion of empty elements, and inclusion of DOCTYPE declarations. ```python doc = Document('') assert doc.to_xml() == "" # DOCTYPE dropped by default assert doc.to_xml_with_options(include_doctype=True) == "" doc = Document("text") # Pretty-print with 2-space indent print(doc.to_xml_with_options(indent=" ")) # # # text # # Expand empty elements (useful for HTML compatibility) print(doc.to_xml_with_options(expand_empty_elements=True)) # "text" ``` -------------------------------- ### QName Equality and Hashing Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Illustrates that QName equality is determined by local name and namespace URI, ignoring the prefix. This allows QNames with different prefixes but the same name and namespace to be considered equal and used in sets or as dictionary keys. ```python from pyuppsala import QName # Same namespace, different prefix -- equal a = QName("item", namespace_uri="urn:ex", prefix="a") b = QName("item", namespace_uri="urn:ex", prefix="b") print(a == b) # True # Can be used in sets and as dict keys names = {a, b} print(len(names)) # 1 ``` -------------------------------- ### Create XsdValidator from File Path Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Instantiate an XsdValidator using the `from_file` static method. This method resolves schema includes, imports, and redefines relative to a specified base path, which is essential for modular schemas. ```python import os schema_dir = "/path/to/schemas" with open(os.path.join(schema_dir, "main.xsd")) as f: schema_xml = f.read() validator = XsdValidator.from_file(schema_xml, schema_dir) ``` -------------------------------- ### XmlWriter.write_declaration_full(version='1.0', encoding=None, standalone=None) Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Writes an XML declaration with custom parameters for version, encoding, and standalone status. ```APIDOC ## write_declaration_full(version='1.0', encoding=None, standalone=None) ### Description Write an XML declaration with custom parameters. ### Method `write_declaration_full(version='1.0', encoding=None, standalone=None)` ### Parameters - **version** (str) - Optional - The XML version (default: '1.0'). - **encoding** (str | None) - Optional - The character encoding. - **standalone** (bool | None) - Optional - Whether the document is standalone. ### Example ```python w = XmlWriter() w.write_declaration_full("1.0", encoding="ISO-8859-1", standalone=True) # ``` ### Returns `None` ``` -------------------------------- ### etree Module Compatibility Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Provides an lxml.etree-compatible API for common XML operations. ```APIDOC ## pyuppsala.etree ### Description An lxml.etree-compatible API including `Element`, `SubElement`, `fromstring`, `tostring`, `find`/`findall`, `XPath`, `XMLSchema`, and more. ``` -------------------------------- ### Parse, Query, and Modify XML Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Demonstrates how to parse an HTML-like string, find elements by tag name, retrieve attributes and text content, add new elements and text nodes, and serialize the modified document back to XML. ```python from pyuppsala import Document xml = """

Hello

World

""" doc = Document(xml) # Find all

elements paragraphs = doc.get_elements_by_tag_name("p") for p in paragraphs: print(f"{p.get_attribute('class')}: {p.text_content}") # Add a new paragraph body = doc.get_elements_by_tag_name("body")[0] new_p = doc.create_element("p") new_p.set_attribute("class", "footer") text = doc.create_text("Goodbye") doc.append_child(new_p, text) doc.append_child(body, new_p) print(doc.to_xml_with_options(indent=" ")) ``` -------------------------------- ### to_xml_with_options Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes the document to an XML string with customizable formatting options. ```APIDOC ## to_xml_with_options(indent=None, expand_empty_elements=False, include_doctype=False) -> str ### Description Serialize with formatting options. ### Parameters #### Query Parameters - **indent** (str) - Optional - Indentation string (e.g. " "), or `None` for compact output. - **expand_empty_elements** (bool) - Optional - If `True`, write `` instead of ``. - **include_doctype** (bool) - Optional - If `True` and the document preserved a `` declaration, serialize it ahead of the root element. Defaults to `False`. ### Request Example ```python doc = Document('') assert doc.to_xml() == "" # DOCTYPE dropped by default assert doc.to_xml_with_options(include_doctype=True) == "" doc = Document("text") # Pretty-print with 2-space indent print(doc.to_xml_with_options(indent=" ")) # # # text # # Expand empty elements (useful for HTML compatibility) print(doc.to_xml_with_options(expand_empty_elements=True)) # "text" ``` ``` -------------------------------- ### Serialize Node to XML with Formatting Options Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes a node's subtree to XML, allowing for custom formatting options like indentation. Use this for pretty-printing XML output. ```python doc = Document("") a = doc.document_element.children[0] print(a.to_xml_with_options(indent=" ")) # # # ``` -------------------------------- ### Write Custom XML Declaration Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Generate an XML declaration with specific version, encoding, and standalone attributes using `write_declaration_full`. ```python w = XmlWriter() w.write_declaration_full("1.0", encoding="ISO-8859-1", standalone=True) # ``` -------------------------------- ### Create and Append Element Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use `create_element` to create a new element node, which can then be appended to the document tree using `append_child`. Elements can also be created with namespaces. ```python doc = Document.empty() root = doc.create_element("root") doc.append_child(doc.root, root) # With namespace prefix child = doc.create_element("item", namespace_uri="urn:ex", prefix="x") doc.append_child(root, child) print(doc.to_xml()) # '' ``` -------------------------------- ### Create Processing Instruction Node Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Use `create_processing_instruction` to create a new processing instruction node. It can be inserted before other nodes in the document. ```python doc = Document("") pi = doc.create_processing_instruction("xml-stylesheet", 'type="text/xsl" href="style.xsl"') doc.insert_before(doc.root, pi, doc.document_element) print(doc.to_xml()) # ``` -------------------------------- ### Check Element Names with Namespace Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/quickstart.md Use `matches_name_ns()` to check if an element matches a given namespace URI and local name. ```python from pyuppsala import Document xml = 'ok' doc = Document(xml) root = doc.document_element if root.matches_name_ns("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion"): print("This is a SAML Assertion") ``` -------------------------------- ### XSD Regex Patterns with Pyuppsala Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Illustrates the use of XsdRegex for pattern matching, including US ZIP codes, Unicode letter categories, and character class subtraction. Ensure the regex patterns are correctly formatted for XSD compatibility. ```python from pyuppsala import XsdRegex # US ZIP code zip_re = XsdRegex(r"[0-9]{5}(-[0-9]{4})?") print(zip_re.is_match("12345")) # True print(zip_re.is_match("12345-6789")) # True print(zip_re.is_match("abcde")) # False # Unicode letter categories letters = XsdRegex(r"\p{L}+") print(letters.is_match("Hello")) # True print(letters.is_match("12345")) # False # Character class subtraction (vowels removed) consonants = XsdRegex(r"[a-z-[aeiou]]+") print(consonants.is_match("bcdfg")) # True print(consonants.is_match("abcde")) # False ``` -------------------------------- ### Schema Validation with Detailed Errors Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md Illustrates how to validate XML documents against an XSD schema using `XsdValidator`. It demonstrates validating both a correct document and an incorrect one, printing detailed error messages for validation failures. ```python from pyuppsala import XsdValidator schema = """ " validator = XsdValidator(schema) # Valid document errors = validator.validate_str( 'Alice30' ) assert len(errors) == 0 # Invalid: missing required attribute, wrong element order errors = validator.validate_str( "-5Bob" ) for err in errors: print(f" Line {err.line}, Col {err.column}: {err.message}") ``` -------------------------------- ### Document Constructor Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Parses an XML string into a DOM document. Supports optional parameters for controlling parsing depth, entity expansion, and namespace awareness. ```APIDOC ## Document Constructor ### Description Parses an XML string into a DOM document. Supports optional parameters for controlling parsing depth, entity expansion, and namespace awareness. ### Parameters * **xml** (string) - A well-formed XML string. * **max_depth** (int, optional) - Maximum parsing depth. * **max_entity_expansion** (int, optional) - Maximum entity expansion. * **namespace_aware** (bool, optional) - Whether to parse in namespace-aware mode. ### Example ```python from pyuppsala import Document doc = Document("XML Guide") print(doc.document_element.tag.local_name) # "catalog" ``` ``` -------------------------------- ### Matching Standalone QName Objects Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/examples.md The `QName.matches()` method can be used on standalone `QName` objects to check if they match a given name and namespace URI. This is helpful for building dispatch tables or validating QNames against expected patterns. ```python from pyuppsala import QName # Build a dispatch table handlers = { ("urn:app", "create"): lambda: "Creating...", ("urn:app", "delete"): lambda: "Deleting...", } q = QName("create", namespace_uri="urn:app", prefix="app") for (ns, name), handler in handlers.items(): if q.matches(name, namespace_uri=ns): print(handler()) # "Creating..." ``` -------------------------------- ### to_xml Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes the document to a compact XML string. ```APIDOC ## to_xml() -> str ### Description Serialize the document to a compact XML string. ### Request Example ```python doc = Document(" ") print(doc.to_xml()) # " " ``` ``` -------------------------------- ### XmlWriter.write_declaration() Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Writes the standard XML declaration: . ```APIDOC ## write_declaration() ### Description Writes the standard XML declaration ``. ### Method `write_declaration()` ### Returns `None` ``` -------------------------------- ### Write Processing Instructions Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Add a processing instruction to the XML output using `processing_instruction`. The target must be a valid XML name and not the reserved 'xml'. ```python w = XmlWriter() w.processing_instruction("xml-stylesheet", 'type="text/xsl" href="style.xsl"') print(w.to_string()) ``` -------------------------------- ### matches_name_ns Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Checks if the current element matches the given namespace URI and local name. ```APIDOC ## matches_name_ns(namespace_uri: str, local_name: str) -> bool ### Description Check whether this element matches the given namespace URI and local name. Returns `False` for non-element nodes. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method None (Python method) ### Endpoint None (Python method) ### Request Example ```python doc = Document('text') root = doc.document_element print(root.matches_name_ns("urn:example", "root")) # True print(root.matches_name_ns("urn:other", "root")) # False # Text nodes always return False text_node = root.children[0] print(text_node.matches_name_ns("urn:example", "root")) # False ``` ### Response #### Success Response - **return value** (bool) - True if the element matches the specified namespace and local name, False otherwise. ``` -------------------------------- ### to_xml_with_options Source: https://github.com/kushaldas/pyuppsala/blob/main/docs/api.md Serializes the node's subtree to an XML string with specified formatting options like indentation. ```APIDOC ## to_xml_with_options(indent: str | None = None, expand_empty_elements: bool = False) -> str ### Description Serialize this subtree with formatting options. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method None (Python method) ### Endpoint None (Python method) ### Request Example ```python doc = Document("") a = doc.document_element.children[0] print(a.to_xml_with_options(indent=" ")) # # # ``` ### Response #### Success Response - **return value** (str) - The formatted XML string representation of the subtree. ``` -------------------------------- ### Run Pyuppsala Test Suite Source: https://github.com/kushaldas/pyuppsala/blob/main/README.md Execute the project's test suite using pytest. Ensure all tests pass after making changes. ```bash # Run the test suite uv run pytest ```