Donner SVG 0.8.0
0.8.0 ยท ebf353960.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::xml::XMLDocument Class Reference

Represents an XML document, which holds a collection of XMLNode as the document tree. More...

#include "donner/base/xml/XMLDocument.h"

Classes

struct  NodeInsertion
 One completed source-less node insertion and the source delta insertNode returned. More...

Public Member Functions

 XMLDocument ()
 Constructor to create an empty XMLDocument.
Registry & registry ()
 Get the underlying ECS Registry, which holds all data for the document, for advanced use.
std::shared_ptr< Registry > sharedRegistry () const
 Gets the registry as a shared pointer, for advanced use.
XMLNode root () const
 Get the root XMLNode of the document.
EntityHandle rootEntityHandle () const
 Get the root ECS Entity of the document, for advanced use.
bool hasSourceStore () const
 Return true if this document has an owned source store.
std::string_view source () const
 Return the current XML source text.
std::uint64_t sourceVersion () const
 Return the source version, or 0 for documents without a source store.
bool declaresDoctypeInternalSubset () const
 Whether the parse that built this document resolved a DOCTYPE internal subset, i.e.
std::optional< ParseDiagnostic > sourceDiagnostic () const
 Return the pending source diagnostic, if any.
XMLSourceStore * sourceStore ()
 Get the mutable source store, or nullptr if this document does not own source text.
const XMLSourceStore * sourceStore () const
 Get the immutable source store, or nullptr if this document does not own source text.
std::shared_ptr< const XMLSourceStore > sharedSourceStore () const
 Owning read-only handle to the current source store, for identity-bound recovery.
std::optional< XMLNode > nodeAtSourceOffset (std::size_t offset) const
 Return the deepest parsed XML node whose current source range contains offset.
std::optional< XMLAttributeAtSourceOffset > attributeAtSourceOffset (std::size_t offset) const
 Return the attribute whose current source range contains offset, if any.
ApplySourceEditResult applySourceEdit (const XMLEditIntent &intent)
 Apply a source edit through this XML document.
void setSourceEditTreeLimits (std::size_t maximumTreeNodes, std::size_t maximumTreeDepth)
 Set document-wide tree limits enforced transactionally by incremental source edits.
std::uint64_t remainingSourceEditTreeNodeBudget () const
 Number of additional non-document XML nodes the structural-edit budget allows. Detached XML nodes already owned by this document count against the budget.
ApplySourceEditResult setAttribute (XMLNode node, const XMLQualifiedNameRef &name, std::string_view value)
 Set an XML attribute through this document and update owned source text.
ApplySourceEditResult removeAttribute (XMLNode node, const XMLQualifiedNameRef &name)
 Remove an XML attribute through this document and update owned source text.
ApplySourceEditResult insertNode (XMLNode parent, XMLNode node, std::optional< XMLNode > referenceNode=std::nullopt)
 Insert an XML node under a source-backed element and update owned source text.
ApplySourceEditResult removeNode (XMLNode node)
 Remove a source-backed XML node through this document.
ApplySourceEditResult revertNodeInsertions (std::span< const NodeInsertion > insertions)
 Revert node insertions that are the most recent edits to this document's source.
ApplySourceEditResult setElementText (XMLNode element, std::string_view text)
 Replace an element's text content through this document and update owned source text.
void setSource (std::string source, std::size_t maximumSourceSize=16 *1024 *1024)
 Install owned source text for this document, replacing its source store if it has one.

Static Public Member Functions

static XMLDocument CreateFromRegistry (std::shared_ptr< Registry > registry)
 Rehydrate an XMLDocument facade from an internal shared registry.

Detailed Description

Represents an XML document, which holds a collection of XMLNode as the document tree.

Each XMLNode may only belong to a single document, and each document can have only one root. XMLDocument is responsible for managing the lifetime of all elements in the document, by storing a shared pointer to the internal Registry data-store.

Data is stored using the Entity Component System (Entity Component System (ECS)) pattern, which is a data-oriented design optimized for fast data access and cache locality, particularly during rendering.

XMLDocument and XMLNode provide a facade over the ECS, and surface a familiar Document Object Model (DOM) API to traverse and manipulate the document tree, which is internally stored within Components in the ECS. This makes XMLNode a thin wrapper around an Entity, making the object lightweight and usable on the stack.

See also
XMLNode
Entity Component System (ECS)

Class Documentation

◆ donner::xml::XMLDocument::NodeInsertion

struct donner::xml::XMLDocument::NodeInsertion

One completed source-less node insertion and the source delta insertNode returned.

Class Members
XMLSourceDelta insertion The pure-insertion source delta that inserted the node.
XMLNode node Node that was inserted.

Constructor & Destructor Documentation

◆ XMLDocument()

donner::xml::XMLDocument::XMLDocument ( )

Constructor to create an empty XMLDocument.

To load a document from an XML file, use donner::xml::XMLParser.

Member Function Documentation

◆ applySourceEdit()

ApplySourceEditResult donner::xml::XMLDocument::applySourceEdit ( const XMLEditIntent & intent)

Apply a source edit through this XML document.

This is the incremental editing entry point. It validates the caller's source version, applies the source change through XMLSourceStore, chooses the smallest implemented reparse scope, and emits XML mutations for scopes that can update the live tree.

Implemented local scopes keep source bytes current and either update the live tree or return a scoped diagnostic so callers can preserve the last valid semantic projection while the edited XML is temporarily malformed. Documents parsed with an internal DTD subset or disabled entity translation require Document-scope recovery: draft bytes change, but decoded live values stay untouched. A caller must reparse with the original XMLParser::SourceOptions policy, or keep the diagnostic and last valid tree rather than reinterpret it with broader defaults.

Parameters
intentSource edit request.

◆ attributeAtSourceOffset()

std::optional< XMLAttributeAtSourceOffset > donner::xml::XMLDocument::attributeAtSourceOffset ( std::size_t offset) const

Return the attribute whose current source range contains offset, if any.

Resolves the deepest node containing offset, then checks each of its attributes, using the attribute's tracked source range when it has one and otherwise reparsing the node's current opening tag.

Parameters
offsetByte offset in the current XML source.

◆ CreateFromRegistry()

XMLDocument donner::xml::XMLDocument::CreateFromRegistry ( std::shared_ptr< Registry > registry)
static

Rehydrate an XMLDocument facade from an internal shared registry.

Parameters
registryShared XML document registry to wrap.

◆ declaresDoctypeInternalSubset()

bool donner::xml::XMLDocument::declaresDoctypeInternalSubset ( ) const

Whether the parse that built this document resolved a DOCTYPE internal subset, i.e.

a <!DOCTYPE root [ ... ]> whose bracketed declarations the parser consumed.

The parser expands entity references and does not keep the declarations in the tree, so a consumer that reproduces the document from the tree (the viewport export, for example) cannot reproduce them and must refuse rather than emit a body carrying entity references that nothing declares. This reports what the parser resolved, not a scan of the source text: a <!DOCTYPE inside a comment or a processing instruction is not a DOCTYPE.

setSource clears it, since installing whole new source hands responsibility for the tree back to a full reparse. Incremental fragment reparses leave it alone; they never see the prolog, so they cannot observe that the subset is gone.

◆ insertNode()

ApplySourceEditResult donner::xml::XMLDocument::insertNode ( XMLNode parent,
XMLNode node,
std::optional< XMLNode > referenceNode = std::nullopt )

Insert an XML node under a source-backed element and update owned source text.

A source-less, unparented node is serialized and inserted, emitting an XMLMutation::Kind::NodeInserted mutation. A source-backed element that is already in the tree is moved instead: its existing source bytes are relocated, and a XMLMutation::Kind::NodeRemoved mutation precedes the NodeInserted one. If referenceNode is set, it must be an existing child of parent and the node is inserted immediately before it; otherwise the node is appended before parent 's closing tag, and a self-closing parent is expanded into an opening and closing tag pair.

Parameters
parentElement node to receive the inserted child.
nodeSource-less node to insert, or source-backed element to move.
referenceNodeOptional existing child to insert before.

◆ nodeAtSourceOffset()

std::optional< XMLNode > donner::xml::XMLDocument::nodeAtSourceOffset ( std::size_t offset) const

Return the deepest parsed XML node whose current source range contains offset.

This is the first source-position lookup primitive used by incremental editing. It resolves node source anchors before comparing offsets, so source edits made through XMLSourceStore are reflected without reparsing the full document.

Parameters
offsetByte offset in the current XML source.

◆ removeAttribute()

ApplySourceEditResult donner::xml::XMLDocument::removeAttribute ( XMLNode node,
const XMLQualifiedNameRef & name )

Remove an XML attribute through this document and update owned source text.

This is the DOM-side structured editing entry point for source-backed attribute removals. It removes the serialized attribute through XMLSourceStore, updates the live DOM attribute set, and emits an XMLMutation::Kind::AttributeRemoved mutation.

Parameters
nodeElement node that owns the attribute.
nameAttribute name to remove.

◆ removeNode()

ApplySourceEditResult donner::xml::XMLDocument::removeNode ( XMLNode node)

Remove a source-backed XML node through this document.

This applies the source removal through XMLSourceStore, detaches node from the live XML tree, and emits an XMLMutation::Kind::NodeRemoved mutation.

Parameters
nodeNode to remove.

◆ revertNodeInsertions()

ApplySourceEditResult donner::xml::XMLDocument::revertNodeInsertions ( std::span< const NodeInsertion > insertions)

Revert node insertions that are the most recent edits to this document's source.

insertions lists source-less node insertions in the order they were applied. Their source deltas must be pure insertions (no removed bytes) whose versions run consecutively up to the current source version, and each node's source range must lie within the bytes its delta inserted. Newest first, each delta's bytes are removed and its node is detached with an XMLMutation::Kind::NodeRemoved mutation, so the source returns byte for byte to its state before the first insertion, including the indentation the insertions added. When the list does not meet these conditions, nothing changes and the result carries a diagnostic. If the source store refuses a removal part way, the newer insertions stay reverted and the result is applied with a diagnostic.

Parameters
insertionsInsertions to revert, oldest first.

◆ setAttribute()

ApplySourceEditResult donner::xml::XMLDocument::setAttribute ( XMLNode node,
const XMLQualifiedNameRef & name,
std::string_view value )

Set an XML attribute through this document and update owned source text.

This is the DOM-side structured editing entry point for source-backed attribute writes. It preserves the attribute's existing quote style, escapes value for XML, applies the source change through XMLSourceStore, updates the live DOM attribute, and emits an XMLMutation::Kind::AttributeSet mutation.

Parameters
nodeElement node that owns the attribute.
nameAttribute name to set.
valueRaw unescaped attribute value.

◆ setElementText()

ApplySourceEditResult donner::xml::XMLDocument::setElementText ( XMLNode element,
std::string_view text )

Replace an element's text content through this document and update owned source text.

Elements without element children replace their entire authored content, including CDATA, and detach obsolete non-element nodes. A self-closing element expands when needed. With element children, only the tracked text run is replaced; element children are untouched. Emits a parent XMLMutation::Kind::NodeValueChanged receipt on success. The input may alias the document source or a child value; it is copied before mutation.

Parameters
elementElement whose text content to replace.
textNew raw (unescaped) text content; empty clears the content.

◆ setSource()

void donner::xml::XMLDocument::setSource ( std::string source,
std::size_t maximumSourceSize = 16 *1024 *1024 )

Install owned source text for this document, replacing its source store if it has one.

Pending unreparsed spans are cleared: the caller takes responsibility for rebuilding the tree against the new bytes (as the XML parser does), after which the tree matches the source again.

Every reader sees the new source on its next call: source, sourceVersion and hasSourceStore here, and the same accessors of an SVG document built on this tree. The replaced source is released, so a view from source or a pointer from sourceStore taken before this call must not be used after it, just as a view must not be kept across a source edit. Replacing a source store advances its version past the previous version, so edits recorded against the old source are rejected. Existing nodes lose their source locations until the caller rebuilds the tree against the new bytes.

The XML parser calls this before any other code can reach the document. On a document other code can reach, call it as a source edit is made: for an SVG document, under its write access and on the thread that edits its source, the one thread that may read the source without document access.

Parameters
sourceXML source text to own.
maximumSourceSizeMaximum source size retained after later structured edits.

◆ setSourceEditTreeLimits()

void donner::xml::XMLDocument::setSourceEditTreeLimits ( std::size_t maximumTreeNodes,
std::size_t maximumTreeDepth )

Set document-wide tree limits enforced transactionally by incremental source edits.

Parameters
maximumTreeNodesMaximum live non-document XML nodes after an edit.
maximumTreeDepthMaximum attached element depth after an edit.

◆ source()

std::string_view donner::xml::XMLDocument::source ( ) const

Return the current XML source text.

Documents created programmatically may not have source text; in that case this returns an empty view.

◆ sourceDiagnostic()

std::optional< ParseDiagnostic > donner::xml::XMLDocument::sourceDiagnostic ( ) const

Return the pending source diagnostic, if any.

Incremental source edits commit source bytes before reparsing; when the reparse fails, the tree keeps its last-valid state and the broken span is recorded until a later edit successfully reparses a fragment covering it. A set diagnostic therefore means the tree is stale relative to source, and consumers that need current-source accuracy must fail closed instead of using stale ranges. A later success elsewhere never clears an unrelated broken span.

Documents without a source store never carry a diagnostic.


The documentation for this class was generated from the following file: