PhoenixmlDb.Core

XIncludeProcessor

XInclude 1.0 processor: expands xi:include elements with parse="xml" (structural inclusion) or parse="text" (textual inclusion, SP2) and an href, resolving each reference against the in-scope base URI, recursing into included content, and detecting cyclic / over-deep inclusion.

#XIncludeProcessor

Namespace: PhoenixmlDb.Core.Xml

XInclude 1.0 processor: expands xi:include elements with parse="xml" (structural inclusion) or parse="text" (textual inclusion, SP2) and an href, resolving each reference against the in-scope base URI, recursing into included content, and detecting cyclic / over-deep inclusion.

xpointer / fragid sub-resource selection (SP3) is supported for both an external target (href present, evaluated against the fetched fragment) and a same-document reference (xpointer with no href, evaluated against the master document and guarded against cyclic self-inclusion by containment and bounded by ). The pointer is evaluated via and the selected node-set is spliced in place of the xi:include, with per-element §4.5 xml:base/xml:lang fixup. An empty selection is a fallback-eligible resource error; a selection containing a node that cannot be element content (attribute, document, etc.) is a fatal . parse="text" (SP2) reads the target via — honoring the include's encoding/accept/accept-language attributes — and splices the decoded content in as a single text node in place of the xi:include. A resource error (fetch or decode failure) is fallback-eligible, exactly as for parse="xml"; a fragment identifier in href is still a fatal error (text resources have no fragments). xi:fallback recovery (SP2) IS implemented: a resource error on an xi:include (fetch or parse failure) recovers via a single xi:fallback child's content when present — that content is itself XInclude-processed and replaces the include (an empty fallback simply removes it) — or, absent a fallback, rethrows fatally as before. A misplaced xi:fallback (not a direct child of an xi:include) or more than one on the same xi:include is always a fatal error. xml:base / xml:lang fixup (XInclude 1.0 §4.5): when a top-level included element is spliced into the master, it is stamped with xml:base = the resolved target URI (unless it already carries its own xml:base) and, if it lacks its own xml:lang, with the in-scope xml:lang from the include's ancestor chain (if any). Only the top-level included element is stamped — descendants resolve their base/lang through the added attribute plus their own existing xml:base/xml:lang chain.

#Methods

#AdjustBase(Uri,Xml.XmlElement)

Returns the in-scope base URI for : adjusted by an xml:base attribute on the element itself, if present.

#Expand(Xml.XmlDocument,Uri,PhoenixmlDb.Core.Xml.XIncludeOptions)

Expands every xi:include (parse="xml", href) in , in place, and returns the same mutated document.

Parameters:

  • doc — The document to expand. Mutated in place.

  • baseUri — The absolute base URI of , against which relative hrefs (as adjusted by any in-scope xml:base) are resolved.

  • options — XInclude processing options (resolver, remote policy, depth).

Returns: The same , with its xi:includes expanded.

is expanded in place. On any thrown it is left partially expanded and in an undefined state and MUST be discarded, not reused. In particular, a same-document xpath1() evaluation that exceeds throws while a background thread may still be reading (System.Xml's XPath engine cannot be cancelled mid-evaluation); discarding the document as required avoids racing that reader.

Exceptions:

  • XIncludeException — Thrown on a malformed xi:include (including a malformed xpointer), a cyclic or over-deep inclusion, a resource-safety limit (), or a resource error with no usable xi:fallback. A resource error that is recovered by an xi:fallback does not throw.

#ExpandNode(Xml.XmlDocument,Xml.XmlNode,Uri,PhoenixmlDb.Core.Xml.XIncludeOptions,PhoenixmlDb.Core.Xml.IXmlResourceResolver,Collections.Generic.List<Uri>,PhoenixmlDb.Core.Xml.XIncludeLimiter)

Depth-first walks 's children in , expanding any xi:include elements. is the in-scope base for itself (already adjusted for the ancestors above it).

#GetInScopeLang(Xml.XmlNode)

Returns the in-scope xml:lang for : the nearest xml:lang declared on itself or an ancestor, or null if none is in scope.

#IsAncestorOrSelf(Xml.XmlNode,Xml.XmlNode)

Returns whether is itself or one of its ancestors (walked via ).

#ProcessSameDocumentXPointer(Xml.XmlDocument,Xml.XmlElement,String,Uri,PhoenixmlDb.Core.Xml.XIncludeOptions,PhoenixmlDb.Core.Xml.IXmlResourceResolver,Collections.Generic.List<Uri>,PhoenixmlDb.Core.Xml.XIncludeLimiter)

Handles an xi:include with an xpointer/fragid and no href: the selection is evaluated against itself (same-document XPointer). A selection that is, or contains, the xi:include element is a fatal (containment-based cyclic guard — the URI-stack guard used for fetched targets doesn't apply here since there is no target URI). Any nested xi:include within the selected subtree is expanded (against the master's own base URI, tracked on the same active stack; remains the runaway backstop) before the copies are spliced in.

#ProcessTextInclude(Xml.XmlDocument,Xml.XmlElement,String,Uri,PhoenixmlDb.Core.Xml.XIncludeOptions,PhoenixmlDb.Core.Xml.IXmlResourceResolver,Collections.Generic.List<Uri>,PhoenixmlDb.Core.Xml.XIncludeLimiter)

Handles an xi:include parse="text": resolves to a text resource via (honoring the encoding/accept/accept-language attributes) and splices its content in as a single text node, replacing the xi:include. A resource error (fetch/decode failure) is fallback-eligible, exactly as for parse="xml".

#RecoverWithFallback(Xml.XmlDocument,Xml.XmlElement,Xml.XmlElement,Uri,PhoenixmlDb.Core.Xml.XIncludeOptions,PhoenixmlDb.Core.Xml.IXmlResourceResolver,Collections.Generic.List<Uri>,Exception,Uri,PhoenixmlDb.Core.Xml.XIncludeLimiter)

Handles a resource error (fetch/parse failure) on an xi:include target: recovers via 's content when present, or rethrows fatally when it is not.

#RunOnLargeStack``1(Func<``0>,String,Int32,String)

Runs on a dedicated worker thread with a large explicit stack (see ), waits up to for it ( = wait forever), and rethrows any exception it produced on the caller's thread with the original stack trace preserved. This is what makes the depth guard — and the xpath1() recursion — bounded by the logical limit rather than the physical thread stack. On timeout the worker is abandoned (System.Xml's XPath engine cannot be cancelled) but, being a background thread on its own large stack, it blocks neither process exit nor the and cannot overflow the caller's stack; a fatal is raised instead.

#SetXmlAttribute(Xml.XmlElement,String,String)

Stamps an attribute in the XML namespace (xml:base/xml:lang) on using the reserved xml prefix. Using with the XML namespace but no prefix leaves the attribute prefix empty, so a later serialization (e.g. via OuterXml) invents a bogus prefix and emits an illegal xmlns:…="http://www.w3.org/XML/1998/namespace" redeclaration; binding the reserved xml prefix here keeps the stamped attribute well-formed on round-trip.

#SpliceNodeSet(Xml.XmlDocument,Xml.XmlElement,Collections.Generic.IReadOnlyList<Xml.XmlNode>,Uri,PhoenixmlDb.Core.Xml.XIncludeLimiter)

Imports each node in into and inserts them, in document order, in place of . Applies XInclude §4.5 xml:base/xml:lang fixup to each top-level included element ( = the origin URI). An attribute (or namespace) node cannot be spliced as content and is a fatal .

#Fields

Name Description
XIncludeNamespace The XInclude 1.0 namespace URI.