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 of doc, 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 doc, with its xi:includes expanded.

Exceptions:

  • XIncludeException — Thrown on a malformed xi:include (including a malformed xpointer), a cyclic or over-deep inclusion, a resource-safety limit (XIncludeErrorKind.LimitExceeded), or a resource error with no usable xi:fallback. A resource error that is recovered by an xi:fallback does 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.