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 XIncludeOptions.MaxIncludeDepth). The pointer is evaluated via XPointerEvaluator 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 XIncludeException.
parse="text" (SP2) reads the target via IXmlResourceResolver.ResolveText — 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 ofdoc, against which relativehrefs (as adjusted by any in-scopexml:base) are resolved. -
options— XInclude processing options (resolver, remote policy, depth).
Returns: The same doc, with its xi:includes expanded.
Exceptions:
-
XIncludeException— Thrown on a malformedxi:include(including a malformed xpointer), a cyclic or over-deep inclusion, a resource-safety limit (XIncludeErrorKind.LimitExceeded), or a resource error with no usablexi:fallback. A resource error that is recovered by anxi:fallbackdoes not throw.
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.
#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. |