krikri-xml
Version, currently 0.1.05 versions
- 0.3.1latestSep 28, 2026
- 0.3.0not indexedSep 28, 2026
- 0.2.0not indexedSep 28, 2026
- 0.1.1not indexedSep 28, 2026
- 0.1.0not indexedSep 28, 2026
github.com/weirdbricks/krikri-xml
Clean-room XML 1.0 (Fifth Edition) parser in pure Crystal. No C dependencies - implemented directly from the W3C specification.
Nothing has been indexed for 0.1.0 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.
Installation
# Add this to your shard.yml
dependencies:
krikri-xml:
github: weirdbricks/krikri-xml
version: ~> 0.1.0Then run:
shards installshard.yml
No shard.yml has been indexed for 0.1.0. You can read it on the repository.
Dependencies
Unknown: the shard.yml for this version has not been read yet.
README
This README is the one indexed from the repository at its latest ref, not from the tag for this version.
krikri-xml
A clean-room XML 1.0 (Fifth Edition) parser in pure Crystal. No C
dependencies - the stdlib xml module links libxml2; this shard does not
link any native library at all.
Provenance
Implemented directly from the W3C specification REC-xml-20081126 (Extensible Markup Language (XML) 1.0, Fifth Edition) plus Namespaces in XML 1.0. No code from other implementations was consulted or ported; the specification is the only reference.
Status
- Strict, non-recovering well-formedness parsing (like lxml: any well-formedness violation raises).
- DOM tree (
Document,Element,Text,CData,Comment,ProcessingInstruction,DocumentType) with a mutation API (append_child,add_next_sibling,add_prev_sibling,unlink,text=,set_attribute,delete_attribute) mirroring libxml2 move semantics, with one deliberate deviation: repeatedadd_next_siblingcalls on the same anchor accumulate in insertion order (libxml2 would reverse the run). - Full internal DTD subset processing: ENTITY/ENTITY % declarations, ATTLIST defaults (with per-type attribute-value normalization), and the 4.4/4.5 reference treatment (Included / Included in literal / Bypassed / Forbidden) exactly as specified.
- Namespaces in XML 1.0 (default namespace, prefixed bindings, undeclaring, conflict detection).
to_xmlserialization, with aprettymode mirroring libxml2'sXML::SaveOptions::FORMAT.- XPath 1.0 evaluation (
KXML::XPath), implemented from REC-xpath-19991116 and covered byspec/xpath_spec.cr. Variable references ($name) resolve through an optionalvarsbinding map passed toevaluate/evaluate_nodes; the namespace axis works via synthesized namespace nodes;id()resolves ID attributes declared in the internal DTD subset. Unknown variables and syntax errors raiseKXML::XPath::Error. Name tests follow XPath 1.0 section 2.3: an unprefixed node test matches only no-namespace nodes (the defaultxmlnsdeclaration is not used); pass an explicitns_mapto resolve expression prefixes.
Not implemented (yet):
- External entity / external subset fetching (references to external entities are recognized and rejected - deliberate, since krikri's use is offline).
- Serializer fidelity to libxml2/lxml byte output (the current serializer is spec-shaped, not libxml2-shaped).
Usage
require "krikri-xml"
doc = KXML.parse(%(<root><child a="1">text</child></root>))
doc.root.not_nil!.elements[0]["a"] # => "1"
begin
KXML.parse("<root><a></root>")
rescue e : KXML::Error
e.line # line number of the violation
e.column # column of the violation
end
Deliberate parser policies
The spec mandates behaviors; some operational limits are parser policy defined
as fixed constants on KXML::Parser:
MAX_ELEMENT_DEPTH(2_048, matching libxml2'sXML_MAX_DEPTH) - guards against stack exhaustion on deeply nested documents.MAX_ENTITY_DEPTH(64) andMAX_EXPANDED_BYTES(10M) - guards against billion-laughs attacks. The spec permits a processor to impose limits.- XML version
1.1documents are rejected (this is a 1.0 processor). - Character references and names follow the Fifth Edition productions exactly (NameChar per erratum E09).
Conformance
The W3C XML Conformance Test Suite (xmlts20130923.zip, vendored under
testdata/) runs as a data-driven spec: spec/conformance_spec.cr reads the
sub-catalog files from the zip, parses each catalog with this parser itself,
and runs every test file whose expectations this parser can honestly check.
Results across the 15 sub-catalogs (James Clark xmltest, OASIS/NIST, Sun, IBM, Edinburgh errata-2e/3e/4e, Richard Tobin's Namespaces 1.0 + errata):
- 1,671 passed of 1,981 executed (well-formed accepted, not-wf rejected).
- 310 documented divergences - every one enumerated with its reason in
spec/conformance_spec.cr(KNOWN_DIVERGENCES). They fall into two classes:- 300 IBM PITarget tests expecting 4th-edition Letter/NameChar classes;
this parser implements the 5th-edition
NameStartCharproduction, under which those characters are legal (the suite's own errata-4e tests agree). - Colon-containing names the suite's Name-production tests accept but a Namespaces-aware processor must reject (the suite is self-contradictory here; this parser follows the NS-aware reading, matching rmt-ns10-042/043/044).
- 300 IBM PITarget tests expecting 4th-edition Letter/NameChar classes;
this parser implements the 5th-edition
- 319 skipped - tests that require external entities (
ENTITIESparameter/both/general) or non-UTF-8 encodings, which the parser deliberately does not support.
Development
crystal spec
The specs are organized one file per feature area (spec/parser_spec.cr,
entities_spec.cr, doctype_spec.cr, namespaces_spec.cr,
normalization_spec.cr, mutation_spec.cr, doc_order_spec.cr,
limits_spec.cr,
fuzz_spec.cr, realworld_spec.cr, roundtrip_spec.cr, differential_spec.cr,
xpath_spec.cr, and xpath_corpus_spec.cr), plus the W3C conformance suite
(spec/conformance_spec.cr), which reads
testdata/xmlts20130923.zip and runs every case whose expectations this
parser can honestly check - roughly 2,000 additional cases on top of the unit
specs.
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.1.0- Tagged
- Sep 28, 2026
- Commit
790a2a02a102- Indexed
- not yet
Dependents
Repository
github.com/weirdbricks/krikri-xml
Metadata
- Created
- Sep 29, 2026
- Updated
- Nov 9, 2026
- Synced
- Nov 9, 2026
- Versions
- 5