go-ruby-rexml

Ruby's REXML XML library in pure Go โ€” DOM, parser, serialisers, XPath subset; MRI byte-exact, no cgo.

pure Go ยท zero cgo MRI byte-exact DOM tree model parser + ParseError compact + Pretty single-quoted attrs XPath subset CDATA ยท comments ยท PIs rexml 3.4.4 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-ruby-rexml is a pure-Go (no cgo) reimplementation of the core of Ruby's REXML XML library โ€” the tree model, the parser, the serialisers (the compact default formatter and Formatters::Pretty), and a widely-used subset of XPath โ€” matching MRI's rexml 3.4.4 behaviour without any Ruby runtime. Built from scratch rather than wrapping encoding/xml: REXML keeps text and attribute values raw and still-escaped, defaults to single-quoted attributes, sorts attributes by local name in the compact formatter, self-closes empty elements, and preserves comments / CDATA / PIs verbatim โ€” so ParseDocument(xml).ToString() reproduces REXML::Document.new(xml).to_s byte-for-byte. It was extracted from rbgo's internals into a reusable standalone library and bound by rbgo as a native module just like go-ruby-yaml and go-ruby-erb โ€” differential-tested against MRI, 100% coverage, CI green across 6 arches.

Parse ready

ParseDocument builds a tree of Document / Element / Attribute / Text / Comment / CData / Instruction (PI) / DocType / XMLDecl, preserving raw text, entities, the XML declaration and the DOCTYPE (incl. a bracketed internal subset). Malformed input returns a *ParseError with a byte offset, mirroring REXML::ParseException.

DOM ready

Element{Prefix, Name, Attributes, Children, โ€ฆ} with Add / AddElement / AddAttribute / AddText / SetText, Elements(path), EachElement, ChildElements, Text / GetText / Texts, ElementAt(n) (1-based), FirstElement, QName / ExpandedName / Prefix / NamespaceURI, Root / RootNode. Attributes is an ordered map.

Serialise ready

(*Document).ToString (compact, REXML’s to_s), Write(WriteOptions), and the Pretty(indent) / PrettyString formatter โ€” single-quoted attributes, local-name ordering (compact) vs source order (Pretty), exact entity escaping, numeric references, CDATA / comment / PI round-trip, and self-closing empty elements.

XPath subset ready

XPathFirst / XPathEach / XPathMatch over the common subset: absolute and descendant paths, the * wildcard, child and descendant axes, @attr / @* steps, the text() node test, and [n] / [@attr] / [@attr='v'] predicates with REXML’s per-parent position semantics.

Node model ready

Concrete node types mapping each REXML:: class โ€” Document, Element, Attribute, Attributes (ordered), Text (raw round-trip), Comment, CData, Instruction, DocType, XMLDecl โ€” with raw-byte fidelity on round-trip.

Differential oracle & coverage ready

A wide XML corpus parsed and re-serialised here and by the system ruby (REXML::Document.new(xml).to_s, Formatters::Pretty, REXML::XPath.match), compared exactly via stdin/stdout binmode; 100% coverage, gofmt + go vet clean, green across all six 64-bit Go arches.

A faithful, pure-Go port of Ruby's REXML, cgo disabled, so it cross-compiles and embeds anywhere. Validated differentially against the system ruby binary โ€” output compared byte-for-byte. It is a standalone, reusable module extracted from rbgo's internals, and a backend for the sibling org github.com/go-embedded-ruby.