pub struct PostDocument {Show 13 fields
pub destination: Option<String>,
pub destination_directory: Option<String>,
pub site_directory: Option<String>,
pub source: Option<String>,
pub source_directory: Option<String>,
pub searchpaths: Vec<String>,
pub namespaces: FxHashMap<String, String>,
pub namespace_uris: FxHashMap<String, String>,
pub processing_instructions: Vec<String>,
pub parent_document: Option<Box<PostDocument>>,
pub split_from_id: Option<String>,
pub validate: bool,
pub nocache: bool,
/* private fields */
}Expand description
Post-processing document: wraps an XML document with ID management, namespace tracking, XPath helpers, and a persistent cache.
Port of LaTeXML::Post::Document.
Fields§
§destination: Option<String>Destination file path for this document.
destination_directory: Option<String>Destination directory (derived from destination).
site_directory: Option<String>Site root directory.
source: Option<String>Source file path.
source_directory: Option<String>Source directory.
searchpaths: Vec<String>Search paths for resources.
namespaces: FxHashMap<String, String>Namespace prefix → URI mapping.
namespace_uris: FxHashMap<String, String>URI → prefix reverse mapping.
processing_instructions: Vec<String>Processing instructions from the document.
parent_document: Option<Box<PostDocument>>Parent document (for split sub-documents).
split_from_id: Option<String>ID of document we were split from.
validate: boolWhether to validate the document.
nocache: boolWhether caching is disabled.
Implementations§
Source§impl PostDocument
impl PostDocument
Sourcepub fn new(doc: Document, options: PostDocumentOptions) -> Self
pub fn new(doc: Document, options: PostDocumentOptions) -> Self
Create a new PostDocument wrapping an existing XML document.
Port of Post::Document::new.
Sourcepub fn new_from_file(
path: &str,
options: PostDocumentOptions,
) -> Result<Self, String>
pub fn new_from_file( path: &str, options: PostDocumentOptions, ) -> Result<Self, String>
Create from an XML file.
Port of Post::Document::newFromFile.
Parses with XML_PARSE_HUGE (on top of the crate’s default
recover/noerror/nowarning): without it, libxml2’s hard limits corrupt a
multi-GB parse well before any real malformation — the per-document
dictionary cap poisons the ID table (hundreds of thousands of bogus
“ID X already defined” reports for ids that occur exactly once,
witnessed at ~1.47 GB into the 131 MB book’s core XML) and the parse
dies outright at ~1.71 GB. Post input is our own core serialization,
not attacker-authored XML, so relaxing the limits is safe.
Sourcepub fn new_from_string(
xml: &str,
options: PostDocumentOptions,
) -> Result<Self, String>
pub fn new_from_string( xml: &str, options: PostDocumentOptions, ) -> Result<Self, String>
Create from an XML string.
Port of Post::Document::newFromString.
Sourcepub fn new_document(&self, root: Node, destination: &str) -> Self
pub fn new_document(&self, root: Node, destination: &str) -> Self
Create a new sub-document from an element node.
Port of Perl Post::Document::newDocument.
The element is imported into a fresh XML document.
Resources, processing instructions, and class attributes are copied from the parent.
Sourcepub fn get_document(&self) -> &Document
pub fn get_document(&self) -> &Document
Get a reference to the underlying XML document.
Sourcepub fn get_document_mut(&mut self) -> &mut Document
pub fn get_document_mut(&mut self) -> &mut Document
Get a mutable reference to the underlying XML document.
Sourcepub fn get_document_element(&self) -> Option<Node>
pub fn get_document_element(&self) -> Option<Node>
Get the document’s root element.
Sourcepub fn get_source(&self) -> Option<&str>
pub fn get_source(&self) -> Option<&str>
Get the source path.
Sourcepub fn get_source_directory(&self) -> &str
pub fn get_source_directory(&self) -> &str
Get the source directory.
Sourcepub fn get_search_paths(&self) -> &[String]
pub fn get_search_paths(&self) -> &[String]
Get search paths.
Sourcepub fn get_destination(&self) -> Option<&str>
pub fn get_destination(&self) -> Option<&str>
Get the destination path.
Sourcepub fn get_destination_directory(&self) -> Option<&str>
pub fn get_destination_directory(&self) -> Option<&str>
Get the destination directory.
Sourcepub fn get_site_directory(&self) -> Option<&str>
pub fn get_site_directory(&self) -> Option<&str>
Get the site directory.
Sourcepub fn site_relative_destination(&self) -> Option<String>
pub fn site_relative_destination(&self) -> Option<String>
Return destination relative to site directory.
Port of siteRelativeDestination.
Sourcepub fn site_relative_pathname(&self, pathname: &str) -> Option<String>
pub fn site_relative_pathname(&self, pathname: &str) -> Option<String>
Return a pathname relative to the site directory.
Sourcepub fn get_destination_extension(&self) -> Option<String>
pub fn get_destination_extension(&self) -> Option<String>
Get the destination file extension.
Sourcepub fn to_xml_string(&self) -> String
pub fn to_xml_string(&self) -> String
Serialize the document to an XML string.
Sourcepub fn node_to_string(&self, node: &Node) -> String
pub fn node_to_string(&self, node: &Node) -> String
Serialize a single node (and its subtree) to an XML string. Used to re-derive raw-string features (e.g. SVG-fragment extraction) from the DOM for file-parsed input without ever materializing the whole document.
Sourcepub fn processing_instructions(&self) -> &[String]
pub fn processing_instructions(&self) -> &[String]
The <?latexml …?> processing instructions collected at parse time
(searchpaths, loaded packages/classes, RelaxNG schema, …). Used to
re-derive package-presence sniffs (e.g. package="ar5iv") from the parsed
document when the raw XML string is not held in memory.
pub fn stringify(&self) -> String
Sourcepub fn findnodes(&self, xpath: &str) -> Vec<Node>
pub fn findnodes(&self, xpath: &str) -> Vec<Node>
Find nodes matching an XPath expression.
Port of Post::Document::findnodes.
Sourcepub fn findnodes_at(
&self,
xpath: &str,
context_node: Option<&Node>,
) -> Vec<Node>
pub fn findnodes_at( &self, xpath: &str, context_node: Option<&Node>, ) -> Vec<Node>
Find nodes matching an XPath expression, relative to a given context node.
Sourcepub fn find_split_pages(&self, union_xpath: &str) -> Vec<Node>
pub fn find_split_pages(&self, union_xpath: &str) -> Vec<Node>
Limit-safe evaluation of a --splitat page union.
make_splitpaths emits //ltx:X and
//ltx:X[preceding-sibling::ltx:Y or parent::ltx:Z] arms. As XPath on a
huge document the predicated arms overflow the 10M node-set ceiling (see
scan_ids_and_pis), the union returns NULL, and nothing splits — the
whole document stays one page and the downstream XSLT then dies on the same
ceiling. Instead we parse the arms and select pages with one limit-safe
walk, applying the predicates in Rust: same nodes, document order, no
duplicates, as an XPath union.
Falls back to raw XPath for unions outside that grammar (custom
--splitpaths), which only run on small, limit-safe documents.
Sourcepub fn findnode(&self, xpath: &str) -> Option<Node>
pub fn findnode(&self, xpath: &str) -> Option<Node>
Find the first node matching an XPath expression.
Sourcepub fn findnode_at(&self, xpath: &str, context_node: &Node) -> Option<Node>
pub fn findnode_at(&self, xpath: &str, context_node: &Node) -> Option<Node>
Find the first node matching an XPath expression, relative to a context node.
Sourcepub fn findvalue(&self, xpath: &str) -> Option<String>
pub fn findvalue(&self, xpath: &str) -> Option<String>
Evaluate an XPath expression and return the string value.
Sourcepub fn findnodes_foreign(xpath: &str, node: &Node) -> Vec<Node>
pub fn findnodes_foreign(xpath: &str, node: &Node) -> Vec<Node>
XPath query on an arbitrary node, even if from a different document. Creates a temporary XPath context on the node’s own document.
Sourcepub fn add_namespace(&mut self, prefix: &str, nsuri: &str)
pub fn add_namespace(&mut self, prefix: &str, nsuri: &str)
Register a new namespace prefix → URI mapping.
Port of Post::Document::addNamespace.
Sourcepub fn get_qname(&self, node: &Node) -> Option<String>
pub fn get_qname(&self, node: &Node) -> Option<String>
Get the qualified name (prefix:localname) for a node.
Port of Post::Document::getQName.
Sourcepub fn qname_prefix(&self, node: &Node) -> Option<String>
pub fn qname_prefix(&self, node: &Node) -> Option<String>
Resolve a node’s namespace URI to its registered prefix without
allocating a combined “prefix:localname”. Returns the prefix as an
owned String (a copy of the entry in namespace_uris); callers
can then match on node.get_name() separately. Useful in hot
dispatch code where the format! in get_qname is the cost.
Sourcepub fn is_qname(&self, node: &Node, expected: &str) -> bool
pub fn is_qname(&self, node: &Node, expected: &str) -> bool
Check whether a node’s qualified name equals a fixed “prefix:localname”
string without allocating a String. Fast-path for hot comparisons
like is_qname(node, "ltx:XMApp") — avoids the format! in
get_qname when the caller only needs a boolean answer. Falls back
to allocating comparison (via get_qname) for unknown-namespace
cases so semantics exactly match get_qname(node).as_deref() == Some(...).
Sourcepub fn record_id(&mut self, id: &str, node: Node)
pub fn record_id(&mut self, id: &str, node: Node)
Record an ID → node mapping.
Port of Post::Document::recordID.
Sourcepub fn find_node_by_id(&self, id: &str) -> Option<&Node>
pub fn find_node_by_id(&self, id: &str) -> Option<&Node>
Find a node by its xml:id.
Port of Post::Document::findNodeByID.
Sourcepub fn idcache_len(&self) -> usize
pub fn idcache_len(&self) -> usize
Number of id-bearing nodes registered in this document’s idcache.
This is exactly the node set Perl’s //@xml:id iterates.
Sourcepub fn idcache_iter(&self) -> impl Iterator<Item = (&String, &Node)>
pub fn idcache_iter(&self) -> impl Iterator<Item = (&String, &Node)>
Iterate (id, node) for every id-bearing node in this document, in
arbitrary order. Mirrors Perl’s //@xml:id traversal (per-document,
so bounded by the page size rather than the global ObjectDB).
Sourcepub fn uniquify_id(&mut self, baseid: &str, suffix: Option<&str>) -> String
pub fn uniquify_id(&mut self, baseid: &str, suffix: Option<&str>) -> String
Generate a unique ID based on baseid, optionally applying a suffix.
If the resulting ID is already used (and not marked reusable), appends alphabetic suffixes (a, b, c, …) until unique.
Port of Post::Document::uniquifyID.
Sourcepub fn generate_node_id(
&mut self,
node: &mut Node,
prefix: &str,
reusable: bool,
) -> Option<String>
pub fn generate_node_id( &mut self, node: &mut Node, prefix: &str, reusable: bool, ) -> Option<String>
Generate, add, and register an xml:id for a node.
Creates a structured ID relative to the nearest parent with an ID.
Port of Post::Document::generateNodeID.
Sourcepub fn add_nodes(&mut self, parent: &mut Node, data: &[NodeData])
pub fn add_nodes(&mut self, parent: &mut Node, data: &[NodeData])
Add nodes to parent using the recursive representation.
Port of Post::Document::addNodes.
Sourcepub fn remove_nodes(&mut self, nodes: &[Node])
pub fn remove_nodes(&mut self, nodes: &[Node])
Remove nodes from the document, cleaning up ID caches.
Port of Post::Document::removeNodes.
Sourcepub fn preremove_nodes(&mut self, nodes: &[Node])
pub fn preremove_nodes(&mut self, nodes: &[Node])
Mark nodes as “will be removed later” — their IDs become reusable.
Port of Post::Document::preremoveNodes.
Sourcepub fn defer_xmath_unlink(&mut self, node: Node)
pub fn defer_xmath_unlink(&mut self, node: Node)
Queue an XMath subtree for unlinking at the end of post-processing.
Mirrors Perl Post.pm L373-393’s “XMath will be removed (LATER!),
but mark its ids as reusable” pattern. The actual unlink happens
in drain_pending_xmath_unlinks,
which the post-pipeline
invokes once all math-format processors have completed. Without
the defer, parallel-format chains (pmml + cmml) lose the XMath
subtree on the first processor’s unlink and the second
processor’s mark_xm_node_visibility walks stale XMRef
targets, emitting Error:expected:id Cannot find a node with xml:id=….
Sourcepub fn drain_pending_xmath_unlinks(&mut self)
pub fn drain_pending_xmath_unlinks(&mut self)
Drain the deferred XMath unlinks: actually detach each subtree
from the document. Idempotent against multiple processors
queueing the same node — the second unlink_node is a no-op on
an already-detached subtree. The deferred subtrees are wrapped
in DocOwnedNode to suppress libxml’s _Node::drop →
xmlFreeNode chain; the enclosing Document remains the sole
owner. See math_processor::process_math_node for the prior
in-place wrapping pattern.
Sourcepub fn remove_blank_nodes(&self, node: &Node) -> u32
pub fn remove_blank_nodes(&self, node: &Node) -> u32
Remove blank (whitespace-only) text nodes that are direct children of node.
Port of Post::Document::removeBlankNodes.
Sourcepub fn replace_node(&mut self, old_node: &Node, replacements: &[NodeData])
pub fn replace_node(&mut self, old_node: &Node, replacements: &[NodeData])
Replace node with replacements in the document.
Port of Post::Document::replaceNode.
Sourcepub fn prepend_nodes(&mut self, parent: &mut Node, nodes: &[NodeData])
pub fn prepend_nodes(&mut self, parent: &mut Node, nodes: &[NodeData])
Prepend nodes as the first children of parent.
Port of Post::Document::prependNodes.
Sourcepub fn add_ss_values(node: &mut Node, key: &str, values: &str)
pub fn add_ss_values(node: &mut Node, key: &str, values: &str)
Add space-separated values to an attribute, deduplicating and sorting.
Port of Post::Document::addSSValues.
Sourcepub fn add_class(node: &mut Node, class: &str)
pub fn add_class(node: &mut Node, class: &str)
Add CSS class(es) to a node.
Port of Post::Document::addClass.
Sourcepub fn mark_xm_node_visibility(&self)
pub fn mark_xm_node_visibility(&self)
Mark XMath node visibility (content vs presentation branches).
Port of Post::Document::markXMNodeVisibility.
Sourcepub fn realize_xm_node_branch(
&self,
node: &Node,
branch: XMBranch,
) -> Option<Node>
pub fn realize_xm_node_branch( &self, node: &Node, branch: XMBranch, ) -> Option<Node>
Realize an XMRef/XMDual node along a branch — Perl realizeXMNode($node, $branch) (Post.pm L1436-1450), the two-argument form.
Unlike the branchless realize_xm_node below,
this loops: an XMRef is followed to its target, an XMDual is
descended into the requested branch, and either may expose the other, so
resolution repeats until the node is neither. A dangling idref reports
the same expected:id error and yields None.
Sourcepub fn realize_xm_node(&self, node: &Node) -> Option<Node>
pub fn realize_xm_node(&self, node: &Node) -> Option<Node>
Realize an XMRef node: follow the reference to get the “real” node.
Port of Post::Document::realizeXMNode’s one-argument form (Post.pm
L1451-1456) — a single XMRef hop, leaving an XMDual alone. Callers that
need a specific branch want realize_xm_node_branch.
Sourcepub fn conjoin(conjunction: Conjunction, nodes: Vec<NodeData>) -> Vec<NodeData>
pub fn conjoin(conjunction: Conjunction, nodes: Vec<NodeData>) -> Vec<NodeData>
Join a list of nodes with a conjunction.
Port of Post::Document::conjoin.
Sourcepub fn initial(string: &str, force: bool) -> String
pub fn initial(string: &str, force: bool) -> String
Find the initial letter for sorting.
Port of Post::Document::initial.
Sourcepub fn trim_child_nodes(node: &Node) -> Vec<Node>
pub fn trim_child_nodes(node: &Node) -> Vec<Node>
Trim leading/trailing whitespace text nodes from a node’s children.
Port of Post::Document::trimChildNodes.
Add a navigation reference.
Port of Post::Document::addNavigation.
Sourcepub fn validate(&self) -> Result<(), String>
pub fn validate(&self) -> Result<(), String>
Validate the document against its declared schema.
Port of Post::Document::validate.
Sourcepub fn cache_lookup(&self, key: &str) -> Option<String>
pub fn cache_lookup(&self, key: &str) -> Option<String>
Look up a value in the persistent cache.
Sourcepub fn cache_store(&mut self, key: &str, value: &str)
pub fn cache_store(&mut self, key: &str, value: &str)
Store a value in the persistent cache.
Sourcepub fn cache_remove(&mut self, key: &str)
pub fn cache_remove(&mut self, key: &str)
Remove a value from the persistent cache.
Trait Implementations§
Source§impl Drop for PostDocument
impl Drop for PostDocument
Source§fn drop(&mut self)
fn drop(&mut self)
Rationalize Node lifetime between post-processing components.
idcache entries are Node handles into the C-owned libxml
Document tree — the Document owns the lifetime, Node wrappers
are lookup references.
libxml 0.3.9’s _Node::drop fires xmlFreeNode(ptr) whenever
the wrapper’s internal unlinked flag is true. Math processing
calls unlink_node() on nodes as it replaces XMath subtrees
with MathML, flipping that flag for nodes still held by
idcache. The resulting drop sequence is:
document: Document(declared first) →xmlFreeDocwalks the full tree including still-reachable nodes that share memory with idcache entries; freed.idcache: HashMap<String, Node>→ each Node withunlinked=truefiresxmlFreeNodeon already-freed memory → SIGSEGV insidexmlFreeNodeList.
Fix: hand each idcache entry to DocOwnedNode (see
crate::doc_owned_node), which suppresses the inner Rc’s Drop
so xmlFreeNode never fires on already-freed memory.
xmlFreeDoc remains the sole owner of the C node memory.
Per-entry Rc control block leaks (~24 B) — bounded by
per-document idcache size and reclaimed at process exit.
Proper upstream fix: a public set_linked() setter on the
libxml crate’s Node, which would let us relink before drop
rather than leaking.