Skip to main content

tree-sitter-xml-django

Django-XML template language grammar for tree-sitter.

Supports .xml and .rml files using Django template syntax embedded in XML.

Requirements

  • Node.js (for grammar generation)
  • Python 3.x (for Python bindings)
  • tree-sitter CLI

Usage

Python

import tree_sitter_xml_django as ts_xml_django
from tree_sitter import Language, Parser

language = Language(ts_xml_django.language())
parser = Parser(language)

tree = parser.parse(b"<root>{% if condition %}<child/>{% endif %}</root>")

Contributing

First-time setup

Requires Node.js, uv, and Python 3.10+.

# Install Node.js and Python dependencies
make dev

# Install pre-commit hooks
uvx pre-commit install --install-hooks

make dev runs npm install (tree-sitter CLI) and uv sync (Python dev dependencies) in one step.

Common tasks

Command Description
make generate Re-generate src/parser.c from grammar.js
make test Run tree-sitter corpus tests and Python tests
make package Build the Python distribution package

Releasing a new version

To publish a new version of the package to PyPI:

  1. Bump the version field in pyproject.toml (follows semver)
  2. Merge the change to main

CI will detect that the version has no corresponding git tag, publish the package to PyPI, and then push a vX.Y.Z tag to GitHub automatically. No manual tagging or release steps are needed.

If a merge to main does not include a version bump, the publish step is skipped silently.

The external scanner at src/scanner.c

Using the parser requires a binding in your target language that calls the generated file src/parser.c. For more complex "lookahead" rules, src/scanner.c provides a collection of methods that expose tokens referenced in parser.c. It is worth noting that parser.c cannot be edited directly without breaking the synchronisation between grammar.js and parser.c, but scanner.c can be edited so long as the method names don't change. The CI will only detect differences between the generated parser.c file and its grammar rules in grammar.js, and from the perspective of the parser, a change to the method logic doesn't change what it sees - only the method name that it calls.

Paired vs unpaired Django statements

Django template tags fall into two categories, and the grammar treats them very differently.

Unpaired statements (e.g. {% load %}, {% url %}, {% csrf_token %}) stand alone — no body, no closing tag. Because they require no context about what came before or after, the grammar handles them with a single catch-all rule (dj_unpaired_statement) that matches any {% identifier %} not claimed by a more specific rule. The tag name is deliberately not enumerated; knowing it adds nothing to the parse.

Paired statements (e.g. {% block %}...{% endblock %}, {% if %}...{% endif %}) enclose a body and require a matching closing tag. The grammar must know the tag name at parse time in order to look for the correct {% endXXX %} closing token — this is why paired tags are handled by named rules or an explicit whitelist rather than a catch-all.

This distinction explains what happens with an unknown paired tag: because the parser has no rule telling it to look for a closing {% endcustom %}, the opening tag falls through to the catch-all and is recorded as a dj_unpaired_statement. The closing {% endcustom %} is then parsed as a second, separate dj_unpaired_statement. See Unknown paired Django tags under Limitations for the planned fix.

N.B: It's important to note that the {% [tag] %} ... {% end[tag] %} convention is just that, a convention not a rule of Django syntax. Any proposed fix would need to be lenient on paired statements that do not follow this convention.

Not (yet) implemented

Query files (typically found at /queries/*.scm) are not implemented in this grammar. The only use case for this library at the time of writing is programmatic tree manipulation, not editor integration. Implement these if the grammar is ever adopted for editor use (syntax highlighting, language injection, symbol navigation).

Limitations

XML tags spanning Django conditional branches

Django templates sometimes use conditional blocks to select between variants of an XML structure, relying on the template engine to produce valid XML at render time even though the static source is not well-formed XML. Any XML tag that opens or closes across a Django branch boundary — in either direction — will produce incorrect parse trees:

{# open before block, close inside branch — ERROR nodes #}
<keepTogether>
    {% if necf_state %}
        </keepTogether>
    {% elif vic_state %}
        </keepTogether>
    {% endif %}

{# open inside branches, close after block — wrong tree, no ERROR nodes #}
{% if wide %}
    <keepTogether>
{% else %}
    <keepTogether>
{% endif %}
</keepTogether>

The second case appears to parse without ERROR nodes when the pattern sits at the document root, but in practice these templates have a wrapping parent element. Inside XML element content (_node), bare end_tag is not allowed, so the closing tag is silently consumed as the close of the parent element instead, producing a structurally wrong tree.

Adding bare start_tag/end_tag alternatives to regular XML content causes GLR ambiguity: the parser begins treating every ordinary opening tag as a bare node and orphans its close tag, breaking large amounts of valid XML.

The one exception is when both the mismatched open and close tags land inside Django statement bodies (e.g. inside a {% for %} or {% block %} body), because that context already allows bare tags:

{% for item in items %}
    {% if wide %}<keepTogether>{% else %}<keepTogether>{% endif %}
    <para>{{ item }}</para>
    </keepTogether>    {# inside the for body — parses without error #}
{% endfor %}

If a fix becomes necessary: the principled path is an external scanner (C code in src/scanner.c) that maintains a stack of open XML element names. When it encounters a </tag> whose name is not on the stack it emits a distinct _orphan_end_tag token rather than a normal end_tag, allowing the grammar to admit it in _node context without competing with legitimate close tags. This is non-trivial — the scanner needs to coordinate with Django block boundaries — but it avoids the GLR ambiguity that makes the pure-grammar approach unworkable. The same scanner update would also be a natural place to address unknown paired Django tags.

Unknown paired Django tags

The grammar handles known built-in paired tags by name (autoescape, block, filter, for, if, comment, etc.). Any tag not in that list — including third-party or project-specific paired tags — is parsed as two separate dj_unpaired_statement nodes rather than a single dj_paired_statement with a body.

If a fix becomes necessary: the same external scanner approach described above for XML tags applies here. The scanner would maintain a second stack of open Django tag names; when it encounters {% endXXX %}, it checks whether XXX is on the stack and, if so, emits a specialised close token that the grammar uses to close the corresponding dj_paired_statement. This removes the need for a tag whitelist and handles arbitrary custom and third-party tags. Both stacks could be implemented together in a single scanner update.

License

BSD 3-Clause

Metadata

Release files for tree-sitter-xml-django 0.4.2

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

Source distribution (sdist)

Source distribution for tree-sitter-xml-django 0.4.2
File Size Uploaded Provenance
tree_sitter_xml_django-0.4.2.tar.gz 78.2 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for tree-sitter-xml-django 0.4.2
File
tree_sitter_xml_django-0.4.2-cp310-abi3-win_arm64.whl CPython 3.10 abi3 Windows ARM64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64, Linux glibc 2.5+ x86-64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_10_9_x86_64.whl CPython 3.10 abi3 macOS 10.9+ x86-64 Details

Total release size: 496.3 kB

Release files / tree_sitter_xml_django-0.4.2.tar.gz

Download URL tree_sitter_xml_django-0.4.2.tar.gz
Size 78.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4ac791cfe28bfac0fde7fb645439366043331709f31d7e72694e6a4997b914a5
BLAKE2b-256 checksum
How to use checksums
2bad3a943760b7d88129d3f3eb93c616b640a507746bdadfa439939f8a8fd643
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-win_arm64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-win_arm64.whl
Size 39.6 kB
Tags CPython 3.10 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
15bcad9d275945d860a144b25eff20f88a0e473332191f01a06c9e8891d84c88
BLAKE2b-256 checksum
How to use checksums
498baf78c5cad1653ca6ef10e9deaab09d9803f6a0aae3f1c287f2110883f501
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-win_amd64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-win_amd64.whl
Size 40.3 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
594bb267d3a7249f90c36cdde04f0eeb01b5d20529ce1e19f6dcc87c5a1d020b
BLAKE2b-256 checksum
How to use checksums
7a4f68c6072209369c9f25417fec218155036e9e235ccc427499a226e5ac6611
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_x86_64.whl
Size 65.7 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
c13cfa653beeb784ebfdaffde65e02fce38054c416077f7a0a615ff949c885a7
BLAKE2b-256 checksum
How to use checksums
6dcc6b26ab230479929ab431dcfa6ba5fe4c9aa718bf6dac69aa404f723ad8fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-musllinux_1_2_aarch64.whl
Size 67.8 kB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
2ca790ba499a19f243166a78be4a1fd9707344eb92589b7afec9387f5f832a5d
BLAKE2b-256 checksum
How to use checksums
3108b92dab9de57bdb470f0163b1b39249458029152c7586e646e0f051c25169
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 63.0 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
be14f91a2e0895b836550df88b7b4a8cf1a04eae50c1b58c479305e92d5cec36
BLAKE2b-256 checksum
How to use checksums
4ff68391a7b3219f37bb3827fdbd8dc0cb12cba9d92126fabaf960f0f187fd5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 61.9 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 abi3
SHA-256 checksum
How to use checksums
824985d587872d6dc6df13dfeb847724dc743f54d04d46b41e8153b7446a2006
BLAKE2b-256 checksum
How to use checksums
e3d6cc97b1caf93047af31700fb0a6995e7e59969aa59dca862ed927d85dd202
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_11_0_arm64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_11_0_arm64.whl
Size 40.6 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e18d30d0cbb9127883b181c406737bc6a5975b62fe7fbaf80707f5526c627fa2
BLAKE2b-256 checksum
How to use checksums
fb45798e334f93665beacf26440d8bcf5ea3b80b13ffc64e50807088a8161ef4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_10_9_x86_64.whl

Download URL tree_sitter_xml_django-0.4.2-cp310-abi3-macosx_10_9_x86_64.whl
Size 39.3 kB
Tags CPython 3.10 abi3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
ceeb3353a739b4863baa931d40d4ecd8f045fcb2c88b1c7be6949f407e69593d
BLAKE2b-256 checksum
How to use checksums
a806be75f633063bc25cb9e42560476db842900dfc0af5697d70586092c73d64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Security for tree-sitter-xml-django 0.4.2

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.

Full provenance

All 9 files in this release have been uploaded with provenance metadata.

Select from 9 files

Attestation for tree_sitter_xml_django-0.4.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

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.

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