Skip to main content

pygixml: Python Giant XML

Python Versions PyPI version License: MIT Build Status Documentation Status GitHub Stars

pygixml (Python Giant XML) is a Cython framework built on two specialized C++ engines: pugixml for its in-memory DOM parser (XPath, objectify, dictify), and an inlined yxml push parser for true constant-memory streaming. Between the two, pygixml covers everything lxml and xmltodict do: dotted objectify navigation, XPath 1.0, and an xmltodict-compatible dictify, plus a streaming layer neither of them has, which is what makes pygixml the package of choice for big XML and big-data pipelines.

📚 View Full Documentation


Why pygixml?

Speed, memory, and size. pygixml brings pugixml's battle-tested C++ parser directly to Python.

Every parsing/conversion layer pygixml ships (raw DOM, dictify, objectify, jsonify) is measured against lxml, ElementTree, xmltodict, and xmljson in a full, reproducible benchmark suite (see benchmarks/), not summarized here as a handful of numbers that inevitably go stale the moment the code changes. The live, interactive report (refreshed on a schedule, not hand-edited) is on the Performance page.

Two things worth knowing going in, because they're structural (true regardless of which exact numbers the report shows this week), not a one-time measurement:

  • jsonify.stream_dump holds memory flat as input grows. Every DOM-based approach (pygixml's own DOM path included, lxml, xmltodict) allocates roughly in proportion to the input, so its memory use grows with file size. stream_dump never builds a tree at all, so it doesn't: this is a different complexity class (O(1) vs O(n)), not a fixed "X times less" you'd see at only one input size. It costs something in return: see the report's own memory panel for the honest trade-off, not just the part that flatters it.
  • Package size: pygixml installs in well under a megabyte, without vendoring a build of libxml2/libxslt the way lxml does.

Built for big XML

Those benchmark numbers are for documents that fit comfortably in memory. For the documents that don't (multi-gigabyte exports, logs, data dumps), pygixml's streaming layer is the part lxml and xmltodict simply don't have:

  • pygixml.iterfind / dictify.iterdict / jsonify.iterjsonl: yxml-based incremental parsing in constant memory: one element (or one dict, or one JSON line) in flight at a time, regardless of whether the source document is 10 KB or 10 GB.

  • jsonify.stream_dump(xml_path, json_path) (the headline feature) converts a giant XML file into a single, valid, giant JSON file, entirely in C++, in constant memory, with an xmltodict-compatible output shape (same @attr / #text / repeated-siblings-as-array conventions as dictify.parse). No DOM tree is ever built, no intermediate Python dict/list/str is ever allocated, and the file never has to fit in RAM: only an in-place seek-and-patch trick on the output file is used to close JSON arrays correctly as repeated siblings are discovered. As far as we know, this is the only Python package that can do this without buffering the document, the output, or both, and without crashing the process once the file gets genuinely large.

    The memory guarantee is unconditional (verified: ~17MB peak, completely flat from 5K to 640K records, see benchmarks/adhoc/bench_record_shaped.py). The time guarantee is O(n) for the shape almost all real giant XML actually has: one repeated tag per nesting level (<orders><order>...</order>...). It degrades towards O(n²) only in an adversarial shape: two or more different tags repeating and interleaving at the same level for many iterations (e.g. <a>1</a><b>1</b><a>2</a><b>2</b>... with no wrapping element around each pair). If that's genuinely your data shape, jsonify.stream_jsonl (below) sidesteps the problem entirely by not trying to preserve a single JSON document at all.

  • jsonify.stream_jsonl(xml_path, jsonl_path, tag): the file-to-file counterpart of iterjsonl (filters by tag, unlike stream_dump which always converts the whole document): streams straight to a .jsonl file, one matched element per line, same constant-memory, all-C++ guarantee.

from pygixml import jsonify

# A multi-GB XML file in, a multi-GB JSON file out: peak memory stays flat.
jsonify.stream_dump("huge_export.xml", "huge_export.json")

# Or, one record per line:
jsonify.stream_jsonl("huge_export.xml", "huge_export.jsonl", "record")

Features

  • Fast parsing: pugixml's C++ DOM parser, consistently at or near the front across the benchmark suite (see the Performance page)
  • Constant-memory streaming: jsonify.stream_dump holds flat regardless of input size; nothing else compared here does
  • Small footprint: well under a megabyte installed, no bundled libxml2/libxslt
  • Full XPath 1.0: complete query engine with all standard functions
  • Pythonic API: intuitive properties and methods, not a direct C++ mirror
  • objectify: lxml.objectify-style dotted navigation
  • dictify: xmltodict-compatible XML → dict conversion
  • jsonify: direct XML → JSON, in memory or streamed straight to disk in constant memory (stream_dump, stream_jsonl)
  • HTML ↔ XML: parse_html / html_to_xml turn real-world HTML into well-formed XML you can query with XPath, xml_to_html goes back; names XML can't hold are mapped reversibly (encode_name / decode_name)
  • Tree diff / patch: a minimal edit script between two documents (HTML or XML), plus similarity / signature for structural comparison
  • Streaming (iterfind, iterdict, iterjsonl): constant-memory, yxml-based incremental parsing for documents too big to load whole
  • CLI tools: pygixml cat (pretty-print/colorize), pygixml query (XPath/dotted query), pygixml jsonify (convert to JSON), pygixml convert (XML/JSON/YAML/TOON, any direction), pygixml stream (filter giant files in bounded memory): see Command Line Tools
  • Cross-platform: Windows, Linux, macOS
  • Text extraction: recursive text gathering with configurable joins
  • XML serialization: output with custom indentation
  • Node iteration: depth-first traversal of the entire document

Installation

# From PyPI
pip install pygixml

# Or from GitHub
pip install git+https://github.com/MohammadRaziei/pygixml.git

Quick Start

import pygixml

# Parse XML from string
xml = """
<library>
    <book id="1" category="fiction">
        <title>The Great Gatsby</title>
        <author>F. Scott Fitzgerald</author>
        <year>1925</year>
    </book>
    <book id="2" category="fiction">
        <title>1984</title>
        <author>George Orwell</author>
        <year>1949</year>
    </book>
</library>
"""

doc = pygixml.parse_string(xml)
root = doc.root                           # <library>

# Access children and attributes
book = root.child("book")
print(book.name)                          # book
print(book.attribute("id").value)         # 1
print(book.child("title").text())         # The Great Gatsby

# XPath queries
fiction = root.select_nodes("book[@category='fiction']")
print(f"Found {len(fiction)} fiction books")

# Create & save
doc = pygixml.XMLDocument()
root = doc.append_child("catalog")
root.append_child("item").set_value("Hello")
doc.save_file("output.xml")

Properties vs Methods

A quick reference so you don't get tripped up:

Properties (no ()) Methods (need ())
node.name, node.value, node.type node.child(name)
node.parent, node.next_sibling node.first_child()
node.xml, node.xpath node.append_child(name)
attr.name, attr.value node.set_value(v)
doc.root node.select_nodes(query)
node.first_attribute()
node.text()

objectify: dotted navigation

pygixml.objectify provides an lxml.objectify-inspired interface for navigating XML with plain Python attribute access.

from pygixml import objectify

xml = """
<database name="users_db" version="1.2">
    <user-profile id="101" verified="true">
        <first_name>Mohammad</first_name>
        <balance>450.75</balance>
    </user-profile>
    <entry>Value A</entry>
    <entry>Value B</entry>
</database>
"""

root = objectify.from_string(xml)

# Dotted navigation: underscores map to hyphens automatically
print(root.user_profile.first_name)        # ObjectifiedElement(<first_name>)
print(str(root.user_profile.first_name))   # 'Mohammad'

# Automatic type inference for attributes
print(root.version)                        # 1.2   (float)
print(root.user_profile.id)               # 101   (int)
print(root.user_profile.verified)         # True  (bool)

# Text content
print(str(root.user_profile.first_name))  # 'Mohammad'   always str
print(root.user_profile.balance())        # 450.75        type-inferred

# Repeated siblings: indexing and iteration
print(root.entry[0])                      # ObjectifiedElement
print([str(e) for e in root.entry])       # ['Value A', 'Value B']

# Safe attribute access: never raises
print(root.get('version'))                # 1.2
print(root.get('missing', 'default'))     # 'default'

# Search descendants
print(root.find('balance'))               # ObjectifiedElement(<balance>)
print(root.find('balance', recursive=False))  # None  (not a direct child)
print(root.findall('entry'))              # [ObjectifiedElement, ...]

# Write support: modify in place
root.user_profile.first_name = "Ali"      # update child element text
root.version = 2.0                        # update attribute
root.timeout = 30                         # create new child element

# Delete
del root.timeout                          # remove child element
del root.version                          # remove attribute

objectify API

Feature Behaviour
root.child_tag First <child_tag> element; falls back to <child-tag>
root.attr_name Attribute value (type-inferred) when no child matches
root.tag[n] Index into repeated siblings
for e in root.tag Iterate repeated siblings
str(elem) Raw text content, always str
elem() Type-inferred text content
elem.get(name, default) Safe attribute read, never raises
elem.find(tag) First matching descendant, or None
elem.findall(tag) All matching descendants
elem.name = value Update child text or attribute; create child if absent
del elem.name Remove child element or attribute
elem.tag XML tag name string
elem.attrib {name: typed_value} dict of all attributes
elem.xml Serialised XML of the subtree
Child beats attribute When both share a name, child wins (read and write)

dictify: XML to dict

pygixml.dictify converts XML to a nested dict, compatible with the xmltodict library.

from pygixml import dictify

xml = """
<database name="users_db" version="1.2">
    <user-profile id="101" verified="true">
        <first_name>Mohammad</first_name>
        <balance>450.75</balance>
    </user-profile>
    <entry>Value A</entry>
    <entry>Value B</entry>
</database>
"""

# Parse XML → dict
d = dictify.parse(xml)
# {
#   'database': {
#     '@name': 'users_db',
#     '@version': '1.2',
#     'user-profile': {
#       '@id': '101', '@verified': 'true',
#       'first_name': 'Mohammad', 'balance': '450.75'
#     },
#     'entry': ['Value A', 'Value B']
#   }
# }

# Repeated siblings → list automatically
print(d['database']['entry'])             # ['Value A', 'Value B']

# Attributes prefixed with '@'
print(d['database']['@name'])             # 'users_db'

# Custom options
d = dictify.parse(xml,
    attr_prefix='',       # no prefix: attrs and children in same namespace
    cdata_key='text',     # key for text content (default '#text')
    force_list={'entry'}, # always a list, even with one element
    cdata_separator='',   # join text split by child elements (default: first run)
)

# Parse from file
d = dictify.parse_file('data.xml')

# Convert back to XML
xml_out = dictify.unparse(d, pretty=True, indent='\t')
print(xml_out)

dictify API

Parameter Default Description
attr_prefix "@" Prefix added to attribute keys
cdata_key "#text" Key for text content in mixed nodes
force_list None Tag names always wrapped in a list; pass True for all
cdata_separator None Text split by child elements (Hi<br/>x): None keeps the first non-blank run, a string joins all runs ("" gives "Hix")
strip_whitespace False Strip text at both ends (parse / parse_file only)
Function Description
dictify.parse(xml, **opts) Parse XML string → dict
dictify.parse_file(path, **opts) Parse XML file → dict
dictify.unparse(d, pretty, indent, ...) dict → XML string


HTML, diff and patch

import pygixml

# Messy HTML -> well-formed XML, and back
pygixml.html_to_xml("<ul><li>a<li>b<br></ul>")
# '<ul><li>a</li><li>b<br/></li></ul>'
doc = pygixml.parse_html("<ul><li>a<li>b<br></ul>")      # a normal XMLDocument
pygixml.xml_to_html(doc, unwrap="root")
# '<ul><li>a</li><li>b<br></li></ul>'

# Names XML can't hold (o:p, @click, [prop] ...) are mapped reversibly with the
# SQL/XML rules; `case` picks lower-case (default), "keep" or "escape"
pygixml.html_to_xml("<o:p @Click=1>x</o:p>", case="keep")
# '<o_x003A_p _x0040_Click="1">x</o_x003A_p>'
pygixml.decode_name("_x0040_Click")                       # '@Click'

# Edit script between two documents, and applying it
a = pygixml.parse_html("<ul><li>one</li></ul>")
b = pygixml.parse_html("<ul><li>one</li><li>two</li></ul>")
actions = pygixml.diff(a, b)
# [Insert(parent='/ul[1]', position=1, xml='<li>two</li>')]
pygixml.similarity(a, b)                                   # 0.72
pygixml.patch(a, actions)
pygixml.is_equal(a, b)                                     # True

A document from parse_html remembers it came from HTML, so to_html() restores the original names; a document from parse_string keeps its names as they are.

See the HTML and diff pages of the documentation for the options (ignore_whitespace, ignore_comments, class_as_set, keys, ignore_attrs, moves, text_diff).


Command Line Tools

pygixml installs one CLI entry point, pygixml, with three subcommands: no Python code required for one-off queries, conversions, or filtering giant files from a shell pipeline. Every subcommand also works as python -m pygixml <subcommand>.

Subcommand Loads Use it for
pygixml cat full DOM pretty-print (and colorize) an XML file for the terminal: the XML analog of bat/jq -C
pygixml query full DOM ad-hoc XPath / dotted queries: a jq/xq-style tool for XML you can fit in memory
pygixml jsonify (json alias) DOM or streamed converting a whole file to JSON, .json in / out
pygixml stream one record at a time filtering matches out of a file too big to load, bounded memory
pygixml convert full DOM converting between XML, JSON, YAML, TOON and HTML, any direction (--case for HTML names)

pygixml cat: pretty-print and colorize

pygixml cat data.xml                    # pretty + colorized (auto: only
                                         # on a real terminal, and only
                                         # if colorama is installed)
cat data.xml | pygixml cat -            # from stdin
pygixml cat data.xml --color always     # force color even when piped
pygixml cat data.xml --color never      # force plain, no color
pygixml cat data.xml --indent 4         # 4-space indent instead of 2
pygixml cat data.xml -o pretty.xml      # write to a file (never colorized
                                         # by 'auto': a file isn't a tty)

python -m pygixml cat data.xml

Colorizing is fully optional: install it with pip install pygixml[all] (pulls in colorama, along with YAML/TOON support for pygixml convert). Without it, cat still works exactly the same, just without color: plain, pretty-printed XML, same as --color never.

pygixml query

# XPath (starts with / or //)
pygixml query data.xml "//user-profile[@id='101']/first_name"

# dotted, objectify-style (starts with .): first segment names the root
pygixml query data.xml ".database.user_profile.first_name"
pygixml query data.xml ".database.user_profile.@id"      # attribute
pygixml query data.xml ".database.entry[1]"              # index
pygixml query data.xml ".database.entry[*]"              # all siblings
pygixml query data.xml ".database.user_profile.text()"   # text content

# output formats
pygixml query data.xml ".database" --format xml
pygixml query data.xml ".database" --format json --pretty

# just the count, exit code like grep (0 = match, 1 = no match)
pygixml query data.xml ".database.entry[*]" --count

# multiple files, stdin, NUL-separated for xargs -0
pygixml query *.xml ".config.host"
cat data.xml | pygixml query - ".config.host"
pygixml query data.xml ".database.entry[*]" --null | xargs -0 -n1 echo

# python -m form works identically
python -m pygixml query data.xml ".database.user_profile.first_name"

pygixml jsonify: convert a whole file

pygixml jsonify data.xml                        # compact JSON to stdout
pygixml jsonify data.xml -p                     # pretty (2-space indent)
pygixml jsonify data.xml -o data.json           # write to a file
pygixml jsonify data.xml --force-list item      # always make <item> a list
cat data.xml | pygixml jsonify -                # read from stdin

python -m pygixml jsonify data.xml -o data.json
pygixml json data.xml                           # `json` is a short alias

Automatically switches to jsonify.stream_dump (constant memory) for files over 64MB; --stream / --no-stream force one mode or the other regardless of size.

pygixml stream: filter a giant file

Reads the file once via iterparse, tag by tag, holding at most one matched element's subtree in memory: the right tool once a file is too large for pygixml query/pygixml jsonify's DOM mode.

# every <order>, one JSON object per line (JSONL)
pygixml stream orders.xml --tag order

# simple filters: numeric or string, on a child path or an @attribute
pygixml stream orders.xml --tag order --where "total>100"
pygixml stream orders.xml --tag order --where "@status=shipped"

# multiple --where are AND'ed together
pygixml stream orders.xml --tag order \
    --where "@status=shipped" --where "customer=acme"

# a real JSON array instead of JSONL: still one pass, still bounded memory
pygixml stream orders.xml --tag order --where "total>100" --format array -p

# just count, or stop after N
pygixml stream orders.xml --tag order --where "@status=shipped" --count
pygixml stream orders.xml --tag order --limit 10

cat orders.xml | pygixml stream - --tag order
python -m pygixml stream orders.xml --tag order

--where supports =, !=, >, <, >=, <=; the left-hand side is either @attr or a child path like customer / items/item/sku (same syntax as StreamElement.findtext).



pygixml convert: XML, JSON, YAML, TOON, any direction

pygixml convert data.xml -o data.json         # format guessed from extensions
pygixml convert data.xml -o data.yaml
pygixml convert data.json -o data.xml -p      # pretty XML
pygixml convert data.yaml --to toon           # stdout needs --to explicitly
cat data.xml | pygixml convert - --from xml --to json   # stdin needs --from too

python -m pygixml convert data.xml -o data.yaml

Built on :class:pygixml.formats.FormatDocument, a small class wrapping a plain dict (the same @attr/#text/list shape dictify.parse produces), with to_json/to_xml/to_yaml/to_toon and matching from_* classmethods. JSON and XML always work (stdlib json + this package's own dictify); YAML needs PyYAML and TOON needs ctoon (also written by the author of pygixml). Both are optional, and asking for one you don't have gives a clear pip install ... error instead of crashing:

pip install pygixml[all]   # colorama (for `cat`) + PyYAML + ctoon

Like cat/query, this loads the whole document: for XML too big to fit in memory, convert with pygixml jsonify --stream instead.

Advanced Features

Text Content Extraction

import pygixml

xml = """
<root>
    <simple>Hello World</simple>
    <nested>
        <child>Child Text</child>
        More text
    </nested>
    <mixed>Text <b>with</b> mixed <i>content</i></mixed>
</root>
"""

doc = pygixml.parse_string(xml)
root = doc.root

print(root.child("simple").text())                # Hello World
print(root.child("nested").text(join=" | "))      # Child Text | More text
print(root.child("mixed").text(recursive=False))  # Text

XML Serialization

import pygixml

doc = pygixml.XMLDocument()
root = doc.append_child("root")
root.append_child("item").set_value("content")

print(root.xml)
# <root>
#   <item>content</item>
# </root>

print(root.to_string("    "))  # 4-space indent

Document Iteration

import pygixml

doc = pygixml.parse_string("<root><a/><b/></root>")

for node in doc:
    print(f"{node.type:12s} {node.name}")
# document
# element       root
# element       a
# element       b

Modifying XML

import pygixml

doc = pygixml.parse_string("<person><name>John</name></person>")
root = doc.root

root.child("name").set_value("Jane")
root.child("name").name = "full_name"
root.append_child("age").set_value("30")

print(root.xml)
# <person>
#   <full_name>Jane</full_name>
#   <age>30</age>
# </person>

XPath Support

Full XPath 1.0 via pugixml's engine:

import pygixml

xml = """
<library>
    <book id="1" category="fiction">
        <title>The Great Gatsby</title>
        <author>F. Scott Fitzgerald</author>
        <year>1925</year>
        <price>12.99</price>
    </book>
    <book id="2" category="fiction">
        <title>1984</title>
        <author>George Orwell</author>
        <year>1949</year>
        <price>10.99</price>
    </book>
</library>
"""

doc = pygixml.parse_string(xml)
root = doc.root

# Select nodes
books = root.select_nodes("book")
print(f"Found {len(books)} books")

# Predicates
fiction = root.select_nodes("book[@category='fiction']")
print(f"Found {len(fiction)} fiction books")

# Single node
book = root.select_node("book[@id='2']")
if book:
    print(book.node.child("title").text())    # 1984

# Pre-compiled query for repeated use
query = pygixml.XPathQuery("book[year > 1930]")
recent = query.evaluate_node_set(root)
print(f"Found {len(recent)} books published after 1930")

# Scalar evaluations
avg = pygixml.XPathQuery("sum(book/price) div count(book)").evaluate_number(root)
print(f"Average price: ${avg:.2f}")           # Average price: $11.99

has_orwell = pygixml.XPathQuery("book[author='George Orwell']").evaluate_boolean(root)
print(f"Has Orwell books: {has_orwell}")       # Has Orwell books: True

Supported XPath

Category Examples
Node selection //book, /library/book, book[1]
Attributes book[@id], book[@category='fiction']
Boolean ops and, or, not()
Comparisons =, !=, <, >, <=, >=
Math +, -, *, div, mod
Functions position(), last(), count(), sum(), string(), number()
Axes child::, attribute::, descendant::, ancestor::
Wildcards *, @*, node()

Core API

Class / Module Purpose
XMLDocument Document-level operations: load, save, append-child
XMLNode Navigate, read, and modify individual nodes
XMLAttribute Attribute name and value access
XPathQuery Pre-compiled XPath queries for repeated evaluation
XPathNode Single XPath result (wraps a node or attribute)
XPathNodeSet Collection of XPath results
objectify lxml.objectify-style dotted navigation
dictify xmltodict-compatible XML → dict conversion
jsonify Direct XML → JSON: in-memory dumps*, or constant-memory stream_dump/stream_jsonl
iterfind / iterparse yxml-based constant-memory streaming parser, ElementTree-style
pygixml cat, pygixml query, pygixml jsonify, pygixml convert, pygixml stream CLI tools: see Command Line Tools

Module-level functions: parse_string(xml), parse_file(path).


Benchmarks

cmake -S benchmarks -B benchmarks/build
cmake --build benchmarks/build --target pygixml_bench_report

Compares pygixml's parse/dictify/objectify/jsonify against lxml, ElementTree, xmltodict, and xmljson: speed, memory at scale, and install size. Writes the raw numbers to benchmarks/results/*.json; the docs build (sphinx_docs) renders the interactive page from it. See benchmarks/README.md for the full methodology, or the live copy on the Performance page.


Documentation

📖 Full docs: https://mohammadraziei.github.io/pygixml/


Security

pygixml is not affected by the common XML attacks (XXE, Billion Laughs, external DTD retrieval) that lxml/defusedxml guard against, because its two embedded parsers, pugixml (DOM API) and yxml (streaming API), never implement custom entity resolution or external DTD fetching in the first place, so there's no "safe mode" to configure. See #8 for the full technical breakdown.


License

MIT License: see LICENSE.

Enjoy pygixml? Star the repository ⭐ 👉 Star pygixml on GitHub


Acknowledgments

  • pugixml: Fast and lightweight C++ XML library
  • yxml: Tiny, dependency-free streaming XML parser, powering pygixml's constant-memory streaming layer
  • Cython: C extensions for Python
  • scikit-build: Modern Python build system

Metadata

Release files for pygixml 0.15.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pygixml 0.15.0
File Size Uploaded Provenance Actions
pygixml-0.15.0.tar.gz 944.4 kB Without provenance Details for pygixml-0.15.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pygixml 0.15.0
File Actions
pygixml-0.15.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for pygixml-0.15.0-cp310-abi3-win_amd64.whl
pygixml-0.15.0-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details for pygixml-0.15.0-cp310-abi3-win32.whl
pygixml-0.15.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details for pygixml-0.15.0-cp310-abi3-musllinux_1_2_x86_64.whl
pygixml-0.15.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details for pygixml-0.15.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
pygixml-0.15.0-cp310-abi3-macosx_10_9_universal2.whl CPython 3.10 abi3 macOS 10.9+ universal2 (ARM64, x86-64) Details for pygixml-0.15.0-cp310-abi3-macosx_10_9_universal2.whl
pygixml-0.15.0-cp39-cp39-win_amd64.whl CPython 3.9 CPython 3.9 Windows x86-64 Details for pygixml-0.15.0-cp39-cp39-win_amd64.whl
pygixml-0.15.0-cp39-cp39-win32.whl CPython 3.9 CPython 3.9 Windows x86-32 Details for pygixml-0.15.0-cp39-cp39-win32.whl
pygixml-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl CPython 3.9 CPython 3.9 Linux musl 1.2+ x86-64 Details for pygixml-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl
pygixml-0.15.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details for pygixml-0.15.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
pygixml-0.15.0-cp39-cp39-macosx_10_9_universal2.whl CPython 3.9 CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64) Details for pygixml-0.15.0-cp39-cp39-macosx_10_9_universal2.whl
pygixml-0.15.0-cp38-cp38-win_amd64.whl CPython 3.8 CPython 3.8 Windows x86-64 Details for pygixml-0.15.0-cp38-cp38-win_amd64.whl
pygixml-0.15.0-cp38-cp38-win32.whl CPython 3.8 CPython 3.8 Windows x86-32 Details for pygixml-0.15.0-cp38-cp38-win32.whl
pygixml-0.15.0-cp38-cp38-musllinux_1_2_x86_64.whl CPython 3.8 CPython 3.8 Linux musl 1.2+ x86-64 Details for pygixml-0.15.0-cp38-cp38-musllinux_1_2_x86_64.whl
pygixml-0.15.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.8 CPython 3.8 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details for pygixml-0.15.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
pygixml-0.15.0-cp38-cp38-macosx_10_9_universal2.whl CPython 3.8 CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64) Details for pygixml-0.15.0-cp38-cp38-macosx_10_9_universal2.whl

Total release size: 14.0 MB

Release files / pygixml-0.15.0.tar.gz

Download URL pygixml-0.15.0.tar.gz
Size 944.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c51d7514872a9fcabea54acc4a0d4dd939afc13e0037bec46e7ba421ca87f0e9
BLAKE2b-256 checksum
How to use checksums
56a26775f2aff9a2a865b256451f4865daa7994f213b52b62a7f8d5749c87a8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp310-abi3-win_amd64.whl

Download URL pygixml-0.15.0-cp310-abi3-win_amd64.whl
Size 528.2 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
f371b94d50a49055bec6665c82508b1beccbfa7fb9167759d89865b5b8cbb2c3
BLAKE2b-256 checksum
How to use checksums
e486f53230bd5528af9907e8972ea81bb0c214215f52bee07203e50a293522f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp310-abi3-win32.whl

Download URL pygixml-0.15.0-cp310-abi3-win32.whl
Size 441.8 kB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
7ec67b9e4022132fabfca402445ebff5195662a59ce6697416de8130d6de0ea2
BLAKE2b-256 checksum
How to use checksums
fc42c800ec33907208aab5bf079308c44e51720ca369f22f03a59c54f7afcc26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL pygixml-0.15.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
5efbdd3b38c0b1defdd299cd9456afa1ae65ccaf765e2296544c413e0f9d3189
BLAKE2b-256 checksum
How to use checksums
2b1465dee140b4be6c95a9c3de6d3d3b7c36eaa225e13cd74ad05d5b87e2fdf9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL pygixml-0.15.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 674.5 kB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
1168a61f3a636ca45bba99746a8bb7deffeb12649c76902be8f3fce5c65fba5e
BLAKE2b-256 checksum
How to use checksums
f079e42575c5fb5f6434e8419e45ec82ab617548a775928a2046f21628e69cc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp310-abi3-macosx_10_9_universal2.whl

Download URL pygixml-0.15.0-cp310-abi3-macosx_10_9_universal2.whl
Size 991.0 kB
Tags CPython 3.10 abi3 macOS 10.9+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
d691e5be7822f1e2b82e87c8e8cd0133d47b689a240553d5efbbaa12815fedf0
BLAKE2b-256 checksum
How to use checksums
6a631a96edf7d323bc3000a1217997ff4ed9b3db29147f7a4647b294db3afcf5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp39-cp39-win_amd64.whl

Download URL pygixml-0.15.0-cp39-cp39-win_amd64.whl
Size 534.6 kB
Tags CPython 3.9 Windows x86-64
SHA-256 checksum
How to use checksums
2ec2af4dbcc7b14aaa3745328db08bebdc291a9a11bea07ba36e6f73d465eb00
BLAKE2b-256 checksum
How to use checksums
1804468f0da19a0c9de0c751bf03a6c22c58c8f43fe61bd677fa00d926c9f27b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp39-cp39-win32.whl

Download URL pygixml-0.15.0-cp39-cp39-win32.whl
Size 455.2 kB
Tags CPython 3.9 Windows x86-32
SHA-256 checksum
How to use checksums
394257ace0a0ea60ad2940b43e1df604603886cfd937b2d6472d606d571eb806
BLAKE2b-256 checksum
How to use checksums
993b87ee393925d4048c2346c1f09f58dbd211476b5ef04ac75728139f234ea5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl

Download URL pygixml-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.9 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
b3632af0265f1c6ed5b05fd1362a813f0ed6c78aa49a02b02bfec64a88d0ccae
BLAKE2b-256 checksum
How to use checksums
5b42fe8e021a0d50afa067111d2aa8bcb4bb28bbc25b65bf5a6f216ef0f6d529
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL pygixml-0.15.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 691.0 kB
Tags CPython 3.9 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
166282b0d38c2a6b8568ad0248cec0db5f556d7ed484e43d918a625b9983292d
BLAKE2b-256 checksum
How to use checksums
1e8e2502d123c2e939446df60e1e8503a6dd3180ffca8b42a903e9a49be3e0f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp39-cp39-macosx_10_9_universal2.whl

Download URL pygixml-0.15.0-cp39-cp39-macosx_10_9_universal2.whl
Size 1.0 MB
Tags CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
316fd09b53bff10f0960aa01bea29e24d1f4e1ab3a42d9f48ff6de9b2fed8ffa
BLAKE2b-256 checksum
How to use checksums
bc2a140c06661aa344d574834d3d046cd876525f3132bfdf37b3f6eedaaeeef4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp38-cp38-win_amd64.whl

Download URL pygixml-0.15.0-cp38-cp38-win_amd64.whl
Size 505.2 kB
Tags CPython 3.8 Windows x86-64
SHA-256 checksum
How to use checksums
95dfe06234939fbbde70b125431f419f212a5ef53051c8915d02962e33bee215
BLAKE2b-256 checksum
How to use checksums
263bea31707512de005167c115397f10177506115281d9f3dc753aced76af60f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp38-cp38-win32.whl

Download URL pygixml-0.15.0-cp38-cp38-win32.whl
Size 428.5 kB
Tags CPython 3.8 Windows x86-32
SHA-256 checksum
How to use checksums
33d4d437498ea9e7341f56039b00c52148aa4f7c032879f5cb935053510117f9
BLAKE2b-256 checksum
How to use checksums
5e21fc92a84f7cc40995d84519a3765f5ff3ca7dd4874911eba0d8a6b9ad7b97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp38-cp38-musllinux_1_2_x86_64.whl

Download URL pygixml-0.15.0-cp38-cp38-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.8 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
58b3b85f5c17e5b3e36b422878102ad390a7c63883b1d5352b20b163ab97075c
BLAKE2b-256 checksum
How to use checksums
3c0b4ff2433fa877a8a5c953ece092753d7cecef845f629d4b3b9f6b20c31402
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL pygixml-0.15.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 656.8 kB
Tags CPython 3.8 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
980a24b1ae8c20b7f4f3ee8ebbb34b82d4b96f1dac40c27a7ed035cd6b796812
BLAKE2b-256 checksum
How to use checksums
261ba159f7a4b1937ebe2193e1306d89d3992abbd85285cef84bd5ea8cceec52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pygixml-0.15.0-cp38-cp38-macosx_10_9_universal2.whl

Download URL pygixml-0.15.0-cp38-cp38-macosx_10_9_universal2.whl
Size 995.3 kB
Tags CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
55a1f74e97969d1db00c3885b49c305f91fc2d448fcb8215304d67e98f3bb368
BLAKE2b-256 checksum
How to use checksums
5c327deaa1d0af0cebbe9766338a92b4581ddb3bffdc779d80afc4e19ed86ac7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for pygixml 0.15.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page