formats: std/xml tree, reader and writer (step 1 of #78) #429
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Step 1 of #78 (
std/xml). The package's tree, its reader and its writer, with no data binding yet: a document nobody has a type for (ENCODING.md section 8, step 6:Xml().parse(text)answers anXmlNode).torb/s3needs it for listings and errors (FIRST-PARTY.md gap 24), and the WebDAV driver (#67) needs it for multistatus replies.Source
XmlNodeis the tree, noXmlEncode/XmlDecodeis ever written.std/toml(std/toml/src/toml.trb,value.trb,parser.trb,writer.trb) is the model for the layout: a format value with options, a tree type, a parser, a writer, a vendored public suite, a docs page.Design record point
ENCODING.md slice 8 and section 9 ("document formats ... the tree (
XmlNode) for documents"); ROADMAP "Which versions a format supports" (XML row). Decided by the loop:std/xml(std/xml/project.trb,src/lib.trbre-exporting fromxml.trb,node.trb,scanner.trb/parser.trb,writer.trb,error.trb), written in TorbScript, nonative.public type Xml { ... }is the format value with options, asTomlis; step 1 has no option the reader needs, so it isXml()withindent: Int = 0for the writer only.XmlNodeis an ADT with cases for the document, an element (qualified name = namespace URI + local name + prefix, attributes in document order, children), text, CDATA (kept distinct), comment and processing instruction, and the XML declaration'sversion/encoding/standalone. Namespace prefixes are resolved at read time and kept for writing back.Xml.parse(text): Result<XmlNode, XmlError>andXml.write(tree): String. The reader decodes the five predefined entities and numeric character references, normalises line ends and attribute values per XML 1.0 section 2.11 and 3.3.3, enforces well-formedness (names, one root, matching tags, unique attributes, namespace constraints, theCharproduction) and reports line and column inXmlError.DOCTYPEwithout an internal subset is read and kept (its external identifier is never fetched). ADOCTYPEwith an internal subset is refused with anXmlErrorthat says so, until step 2 reads the entities; nothing is ever silently misread.String); the writer escapes&,<and (in attributes)", and round-trips every tree the reader produces to an equal tree.Acceptance criteria
use Xml, XmlNode, XmlError from "std/xml"works;Xml().parse(text)reads XML 1.0 (fifth edition) with namespaces into anXmlNode, andXml().write(tree)writes it back; for every document the reader accepts,parse(write(parse(text)))equalsparse(text).XmlErrorwith line and column (cases: unclosed and mismatched tags, a second root, a duplicate attribute, an undeclared prefix, an illegal character, a bare&,--in a comment).DOCTYPEwith an internal subset is a clearXmlError; one without is accepted; no external entity or DTD is ever fetched or opened.std/xml/testswith its notice: the well-formedness and namespace cases of the W3C XML Conformance Test Suite that carry no internal subset (the notice and licence recorded in the test package; if the licence does not allow vendoring, hand-written cases per production of XML 1.0 and Namespaces in XML 1.0 instead, and the PR says so).docs/standard-library/xml.md(front matter astoml.md, atrb checkexample that parses a small S3ListBucketResultand reads the keys from the tree), listed indocs/standard-library/index.md;torb docs check,docs skill --checkanddoc --check --no-run stdare green; ENCODING.md slice 8 is marked in progress with a short "what the implementation decided" entry for the tree and the DOCTYPE rule.sh tools/gates.sh a); every public declaration has its doc comment; touched files passtorb format --check.Touches the seed?
No.
std/xmlis a new package that the compiler does not import and no std name is looked up by string, so no two-commit rule applies. (If a later step makes the compiler import it, that step carries the seed rule; none is planned.) One or two Conventional Commits:feat(std/xml): ...and, if the diff is large,docs(std/xml): ....Dependencies
Encode/Decodeside (std/encoding) is step 3 of #78, not this step.std/html): HTML has its own parsing algorithm and tree (WEB.md slice 1), no shared code is planned.[loop:torbscript] decided by the loop: first step of epic #78, sized as one PR (tree, reader, writer, docs page, vendored suite; about the size of std/toml). Naming and layout follow std/toml and ENCODING.md slice 8; no seed touch because the compiler does not import std/xml. Set ready.
std/xml#78std/xml#78std/xml#78[loop:torbscript] claim implement by session:loop-torbscript-20261023 until 2026-10-23T19:38Z
[loop:torbscript] implement: std/xml tree, reader and writer (Xml.parse/write, XmlError with line and column, DOCTYPE rule with nothing external opened, 331 hand-written conformance and unit cases because the W3C suite cannot be redistributed, docs page, index, ENCODING slice 8, CONCEPT sentence reconciled), PR #431, CI green (round 2 after a pdisc sidecar fix; tier A, tier B, gates, pdisc all success), next: review. Tokens: roughly 1 context window plus continuation, not tracked more precisely.
std/xmlreads the internal subset: entities, default attributes and an expansion limit (step 2 of #78) #552Xml.decodereads a document into a typed value (step 3a of #78) #570Xml.encodewrites a typed value as an XML document (step 3b of #78) #605