Documentation
¶
Overview ¶
Package xpath implements XPath 2.0: lexing, parsing to an AST, static analysis, and evaluation against an XDM tree.
Index ¶
- Constants
- Variables
- func BacktrackingRegexEnabled() bool
- func BuiltinAtomicTypeCode(local string) (xdm.TypeCode, bool)
- func CastAtomic(a *xdm.Atomic, target xdm.TypeCode) (*xdm.Atomic, error)
- func CastToDerived(a *xdm.Atomic, target xdm.TypeCode, facet string) (*xdm.Atomic, error)
- func CastToUnion(a *xdm.Atomic, st SequenceType) (*xdm.Atomic, bool)
- func CheckItemTypePurity(st SequenceType, where string) error
- func CoerceFunctionItem(v xdm.Sequence, st SequenceType) (xdm.Sequence, bool)
- func DeepEqualSequences(ctx *Context, a, b xdm.Sequence) (bool, error)
- func EffectiveBooleanValue(seq xdm.Sequence) (bool, error)
- func Eval(src string, ctx *Context, ns NamespaceResolver) (xdm.Sequence, error)
- func FormatNumber(num *xdm.Atomic, pic string, df *DecimalFormat) (string, error)
- func FormatNumberArg(args []xdm.Sequence, i int) (*xdm.Atomic, error)
- func FormatNumberArgStrict(args []xdm.Sequence, i int) (*xdm.Atomic, error)
- func FormatNumberString(args []xdm.Sequence, i int) (string, error)
- func FormatNumberVersion(num *xdm.Atomic, pic string, df *DecimalFormat, v Version) (string, error)
- func FragmentIsValidXMLName(uri string) bool
- func GenerateID(it xdm.Item) string
- func GroupingEqual(a, b *xdm.Atomic, coll Collation, implicitTZ int) bool
- func GroupingKey(a *xdm.Atomic, coll Collation, implicitTZ int) (string, error)
- func IsRelativeReference(ref string) bool
- func NamespaceNodesOf(n *xdm.Node) []*xdm.Node
- func OrderAtomics(a, b *xdm.Atomic, coll Collation, implicitTZ int, version Version) (int, bool)
- func RegexpErr(re Regexp) error
- func RegisterCollation(uri string, c Collation)
- func RegisterEXSLTFuncs(l *Library)
- func RegisterHarnessFuncs(l *Library)
- func RegisterXSLTFuncs(l *Library)
- func SerializeAdaptive(seq xdm.Sequence, p SerializeParams) (string, error)
- func SerializeJSON(seq xdm.Sequence, p SerializeParams) (string, error)
- func SetBacktrackingRegex(on bool)
- func TranslateSchemaRegexp(pattern string) (string, error)
- func TranslateSchemaRegexpVersion(pattern string, xsd11 bool) (string, error)
- type ArgumentPlaceholder
- type ArrayConstructor
- type Axis
- type BinaryOp
- type Binding
- type CastExpr
- type Collation
- type CollectionResolver
- type CompileOptions
- type Compiled
- func Compile(src string, ns NamespaceResolver) (*Compiled, error)
- func CompileVersion(src string, ns NamespaceResolver, v Version) (*Compiled, error)deprecated
- func CompileVersionRefFloor(src string, ns NamespaceResolver, v, refFloor Version) (*Compiled, error)deprecated
- func CompileWith(src string, opts CompileOptions) (*Compiled, error)
- func CompileXQuery(src string, ns NamespaceResolver, v Version) (*Compiled, error)deprecated
- func MustCompile(src string, ns NamespaceResolver) *Compiled
- func (c *Compiled) CompatMode() bool
- func (c *Compiled) Eval(ctx *Context) (xdm.Sequence, error)
- func (c *Compiled) EvalBool(ctx *Context) (bool, error)
- func (c *Compiled) EvalString(ctx *Context) (string, error)
- func (c *Compiled) Expr() Expr
- func (c *Compiled) FreeVariables() []xdm.QName
- func (c *Compiled) Source() string
- func (c *Compiled) StaticCalls() []StaticCall
- func (c *Compiled) WithCompatMode(on bool) *Compiled
- func (c *Compiled) WithDefaultCollation(coll Collation) *Compiled
- func (c *Compiled) WithDefaultCollationURI(coll Collation, uri string) *Compiled
- func (c *Compiled) WithStaticBaseURI(base string) *Compiled
- func (c *Compiled) WithStaticHost(v any) *Compiled
- type Context
- func (c *Context) AdoptBudget(src *Context) *Context
- func (c *Context) ChargeBytes(n int) error
- func (c *Context) ChargeItems(n int) error
- func (c *Context) ChargeNodes(n int) error
- func (c *Context) ContextNode() (*xdm.Node, error)
- func (c *Context) Descend() (*Context, error)
- func (c *Context) EntityBudget() *xdm.EntityBudget
- func (c *Context) Err() error
- func (c *Context) HoldByteBudget() *Context
- func (c *Context) HoldItemBudget() *Context
- func (c *Context) LookupVar(name xdm.QName) (xdm.Sequence, bool)
- func (c *Context) WithFocus(item xdm.Item, pos, size int) *Context
- func (c *Context) WithNow(t time.Time) *Context
- func (c *Context) WithVar(name xdm.QName, val xdm.Sequence) *Context
- type ContextCollectionResolver
- type ContextDocumentResolver
- type ContextItem
- type DecimalFormat
- type DocumentResolver
- type DynamicCall
- type DynamicFunctionLibrary
- type EnvironmentResolver
- type Expr
- func Parse(src string, ns NamespaceResolver) (Expr, error)
- func ParseExtended(src string, ns NamespaceResolver) (Expr, error)
- func ParseVersion(src string, ns NamespaceResolver, v Version) (Expr, error)
- func ParseVersionRefFloor(src string, ns NamespaceResolver, v, refFloor Version) (Expr, error)
- func ParseXQuery(src string, ns NamespaceResolver, v Version) (Expr, error)
- type FilterExpr
- type ForExpr
- type FuncCall
- type Function
- type FunctionCall
- type FunctionLibrary
- type FunctionSpec
- type IfExpr
- type InlineFunctionExpr
- type InlineParam
- type InstanceOfExpr
- type KindTest
- type LetExpr
- type Lexer
- type Library
- type Literal
- type LookupExpr
- type MapConstructor
- type NameTest
- type NamedFunctionRef
- type NamespaceResolver
- type NodeTest
- type OSEnvironment
- type Parser
- type PathExpr
- type QuantifiedExpr
- type Regexp
- type SchemaImpureUnionTypes
- type SchemaListTypes
- type SchemaTypes
- type SchemaUnionListMembers
- type SchemaUnionMemberFacets
- type SchemaUnionNames
- type SchemaUnionTypes
- type ScopedFunctionLibrary
- type SequenceExpr
- type SequenceType
- type SerializeParams
- type SimpleMap
- type StaticCall
- type Step
- type StringConcat
- type TextResolver
- type Token
- type TokenKind
- type TreatExpr
- type TreeValidator
- type UnaryOp
- type VarQualifier
- type VarRef
- type Version
Constants ¶
const CodepointCollation = "http://www.w3.org/2005/xpath-functions/collation/codepoint"
CodepointCollation is the one collation this implementation provides. It is the only collation the spec requires every processor to support, and it compares strings by Unicode codepoint.
const HTMLASCIICaseInsensitive = "http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive"
HTMLASCIICaseInsensitive is the collation that compares ASCII letters without regard to case. It is defined by the spec and is the one non-codepoint collation that needs no locale data.
const MaxBytes = 1 << 30
MaxBytes bounds the string content one evaluation may build.
MaxItems bounds how many items an evaluation materialises, and a string is one item however long it is, so nothing bounded the bytes: twenty-six nested "let"s, each concatenating the previous string with itself, is a 1,009-byte expression that returned 671,088,640 bytes without complaint. Four more lines is ten gigabytes. The limits in docs/security.md all bound bytes at ingress -- what a parse, a module or an external entity may read -- and none of them sees a string produced during evaluation.
The bound is set from measurement rather than taste. Instrumenting the charge points and running the suites and the real-world corpora, the largest legitimate accumulation was 14,516,346 bytes, in the XSLT 3.0 suite. The XQuery suite peaked at 4,382,554 -- Constr-cont-document-3, codepoints-to-string over every valid XML codepoint -- the XPath suite at 4,194,304, XSLT 2.0 at 753,560, and the DocBook xslTNG and XSpec corpora, 877 real documents through two large real stylesheets, at 1,031,269. A gibibyte is 74 times the largest of those, so a transform that serialises a big document into one text node or joins a whole corpus is unaffected, which matters more than the bound being tight: a false rejection is a conformance bug, and refusing legitimate work would be worse than the runaway this guards.
The charge is cumulative over the evaluation, not per string, so the doubling chain is refused while it is still doubling -- the step that would cross the bound never allocates.
const MaxDepth = 500
MaxDepth bounds recursive evaluation by default.
It is a denial-of-service guard for a caller evaluating an expression it did not write, not a conformance limit: nothing in the specification caps recursion, and a query is entitled to recurse as deeply as it likes. A caller that trusts its input can raise the bound through Context.MaxDepth, which is what the conformance harnesses do — xslt.TransformOptions has carried the same escape hatch for template recursion all along.
const MaxItems = 5_000_000
MaxItems bounds the number of items an evaluation may materialise.
Depth bounds the stack and Ctx bounds the wall clock, but neither bounds memory: "count(1 to 9999999)" is one shallow, fast expression that allocates nine million *Atomic values and peaked at 1.8 GB of resident memory. The range operator had its own limit, but "for $a in 1 to 3000, $b in 1 to 3000" walked straight past it, because the sequence is built by the for-expression rather than by the range.
The bound is deliberately generous: a real stylesheet over a large document works in thousands of nodes, not tens of millions, so this only fires on input designed to exhaust memory or on a genuine runaway.
const MaxNodes = 2_000_000
MaxNodes bounds the number of nodes one evaluation may construct into result trees.
MaxItems bounds the items an expression materialises and MaxBytes the string content it builds, and a result tree is neither. It is not an intermediate sequence -- it outlives the expression that contributed to it, which is what makes it a result -- and its size is in nodes rather than characters. So a stylesheet whose result is the CROSS PRODUCT of its input passed both budgets without being charged anything: two nested xsl:for-each over //i, a three-line stylesheet, squares the input's node count. Measured, 811 bytes of input built 10,000 nodes, and 24 kB built 9,000,000 nodes and allocated 44 GB over 49 seconds before returning a result. Nothing refused it, because each loop is individually a few thousand items and the limit that could have seen the product does not measure trees.
This memory differs from the other two in being RETAINED rather than transient: the tree is the caller's result and is live until the caller discards it, so no amount of garbage collection reclaims it while it is being built. That is what the bound is drawn from. A constructed node costs on the order of a few hundred bytes of live heap, measured by building trees at two sizes and reading HeapAlloc across a forced collection: 328 bytes per constructed element on darwin/arm64, stable to a tenth of a byte between 160,000 and 640,000 nodes. So two million nodes caps a result tree near 0.6 GB. An earlier note here recorded 672 bytes and a 1.3 GB cap; that figure did not reproduce and no test pinned it. The discrepancy is in the safe direction -- the real ceiling is half what was claimed, so the bound binds sooner than advertised rather than later -- but the number is stated here as an order of magnitude for future reasoning, not as a constant to compute against. Per-node cost varies with node kind, name length and platform, so re-measure before drawing a new bound from it.
Setting it from a margin over legitimate work instead is the instructive failure. Fifty million is a much larger multiple of anything real, and it let the measured case allocate 128 GB over seven minutes before refusing, which is not a memory bound at all; ten million still reached 6.7 GB retained. The bound has to come from the memory it caps.
It is nonetheless far above real work, which is the constraint that matters on the other side. Instrumenting this charge point and running the suites and the real-world corpora, the largest legitimate result tree was 274,719 nodes, in the XSLT suites; the XSpec corpus peaked at 52,607, the XQuery QT3 lane at 35,328, and the DocBook xslTNG corpus at 35,104 across 577 real documents through a large real stylesheet. Two million is seven times the largest of those and thirty-eight times the largest real-world one. A false rejection is a conformance bug, and refusing legitimate work would be worse than the runaway this guards, so the margin is deliberate.
The charge is cumulative over the whole evaluation, not per instruction or per expression, and is never reset -- entities is the precedent. A budget an expression could restart by being a new expression would never see a loop.
const NSEXSLTCommon = "http://exslt.org/common"
NSEXSLTCommon is the namespace of the EXSLT "common" module.
EXSLT is a community extension library from the XSLT 1.0 era, not a W3C specification. It is named here rather than in xdm because nothing in the data model depends on it.
const UCACollation = "http://www.w3.org/2013/collation/UCA"
UCACollation is the URI family defined by XSLT 3.0 section 5.3.3 and F&O 5.3.4 for the Unicode Collation Algorithm. The base URI selects the root (DUCET) collation; query parameters tailor it.
Variables ¶
var ClearedOnDynamicCall []xdm.QName
ClearedOnDynamicCall names variables a host language wants unbound for the duration of a dynamic function call.
XSLT 3.0 section 24.3 clears the current output URI across a dynamic call, and the value is carried as an ordinary variable binding so that it follows the same scoping an expression does. XPath itself has no such notion, so the host registers the name rather than this package knowing it.
var ConstructorArgVar = xdm.QName{
URI: "urn:go-xml:xpath:internal", Local: "constructor-arg",
}
ConstructorArgVar is the name the argument of a schema constructor function is bound to while the cast that defines the constructor is evaluated. It is in a namespace no query or stylesheet can write, so nothing can collide with it or observe it.
var MarkedOnDynamicCall []xdm.QName
MarkedOnDynamicCall names variables a host language wants BOUND, to a single true, for the duration of a dynamic function call.
It is the counterpart of ClearedOnDynamicCall, for a condition the host cannot express by unbinding: XSLT's fn:current() falls back to the context item when nothing bound the current node, which is right for a bare XPath evaluation and wrong across a dynamic call, where XTDE1360 says the function behaves "as if the context item is absent". Clearing cannot say that; a positive marker can.
Functions ¶
func BacktrackingRegexEnabled ¶ added in v1.0.0
func BacktrackingRegexEnabled() bool
BacktrackingRegexEnabled reports the current setting.
func BuiltinAtomicTypeCode ¶ added in v1.0.0
BuiltinAtomicTypeCode returns the type code for a built-in xs: type, given its local name.
It exists so that a caller holding a schema's primitive type — the xsd package, which cannot be imported from here — can map it to the code this engine's values carry, without a second copy of the table in parser_path.go drifting away from the first.
func CastAtomic ¶
CastAtomic converts an atomic value to a target type, per the XPath 2.0 casting table.
Casting is stricter than the string conversions of XPath 1.0: "abc" cast to xs:double is an error (FORG0001), not NaN. Silent NaN is how a validator ends up reporting a document as valid because a numeric comparison quietly became false.
func CastToDerived ¶
CastToDerived casts to a derived type named by its local name, applying the facet that the type code cannot carry. An unknown name falls back to a plain cast to the primitive.
func CastToUnion ¶ added in v1.1.0
CastToUnion applies the function conversion rules for a *pure union type* declared with "as".
XPath 3.1 2.5.5 already makes a value whose type is one of the union's members an instance of the union, so such a value is returned untouched and this is not reached for it. What is left is the one case the conversion rules do convert: an xs:untypedAtomic, which is cast to the first member type that accepts its lexical form — exactly as a cast to the union would.
import-schema-192 declares a variable "as=dateUnion" over a union of xs:date, xs:time and xs:dateTime and selects xs:untypedAtomic('12:00:00'), then asserts the result is an instance of xs:time. Without the conversion the value stayed untyped, matched no member, and every such variable raised XTTE0570 on a value the rules exist to convert for it.
ok is false when st is not a pure union, so the caller keeps whatever answer its ordinary path gave.
func CheckItemTypePurity ¶ added in v1.3.0
func CheckItemTypePurity(st SequenceType, where string) error
ParseSequenceType parses a SequenceType [79] written in src, resolving any prefix in it with ns.
XQuery's typeswitch writes a SequenceType in a position the expression grammar has no production for, so the host has to parse one on its own. It does so by asking this rather than by growing a second type parser, which would have to track every schema type, every kind test and every occurrence rule that this one already knows.
The whole of src must be the type: trailing text is a syntax error rather than something to be ignored, so that "xs:integer)" is refused where the caller's brace matching went wrong.
The type is parsed at XPath 3.1 whatever version the host is at, so a type written in an XQuery 1.0 module's typeswitch may name map() or array() and is accepted. Taking a Version would be the honest signature, but this is exported and the divergence is permissive -- an earlier module is allowed a type it should not have had, and is not given a wrong answer -- so the widening is left in place rather than paid for with a breaking change. CheckItemTypePurity refuses a sequence type whose item type is not a generalized atomic type, which is what an ItemType position requires.
§2.5.4 admits an AtomicOrUnionType in an ItemType only when it names an atomic type or a *pure* union — one whose members are all atomic. A list type, and a union derived by restriction or with a list member, name a type but not an item type, so a name in scope as the one and not the other is XPST0051 rather than a mismatch.
It is exported for XQuery's typeswitch, whose CaseClause takes a SequenceType and so is bound by the same rule. The xpath-internal positions that need it — "instance of", "treat as", a function signature — call the unexported checkNotListType directly; this is the same check under a name a host language can reach, and "where" names the construct for the message.
func CoerceFunctionItem ¶ added in v1.1.0
CoerceFunctionItem applies the function coercion clause of the function conversion rules (section 3.1.5) to a value supplied where st, a typed function test, is declared.
XSLT's own "as" checking lives in a different package but faces the same rule: an xsl:param declared as="function(xs:string) as xs:string" given an inline function whose signature is not a subtype of that must still bind, with the arguments and the result converted at call time. Only the coercion clause is exported — the atomic half of the conversion rules is already implemented on the XSLT side, and duplicating it here would give two answers to the same question.
The occurrence indicator is honoured, so "(function(A) as B)*" coerces every item of the sequence: the clause is about the item type, and a declaration admitting several function items has to admit each of them on the same terms as one.
ok is false when st is not a typed function test, when the cardinality is wrong, or when any item is not a function item of the declared arity; the caller then reports the mismatch in whatever code its context requires.
func DeepEqualSequences ¶ added in v1.2.0
DeepEqualSequences reports whether two sequences are deep-equal, which is what fn:deep-equal answers.
ctx supplies the collation string comparison uses; a nil ctx takes the default one.
func EffectiveBooleanValue ¶
EffectiveBooleanValue computes fn:boolean over a sequence.
XPath 2.0 restricts this compared with 1.0: a sequence of two or more atomic values raises FORG0006 rather than being truthy. That strictness is deliberate — it catches "if ($seq)" where the author meant "if (exists($seq))" — so it is enforced rather than relaxed.
func Eval ¶
Eval is a one-shot compile-and-evaluate, for callers that will not reuse the expression.
func FormatNumber ¶ added in v1.1.0
formatNumber2 implements fn:format-number.
The picture language is small but has three rules that a naive implementation misses: the '#' and '0' digit characters mean *minimum* versus *optional* places rather than literal digits, grouping size comes from the position of the last separator rather than being fixed at three, and a picture may carry two sub-pictures separated by ';' where the second is used for negative numbers instead of prefixing a minus sign.
func FormatNumberArg ¶ added in v1.1.0
FormatNumberArg is the lenient reading, in which a value that will not convert becomes NaN. XSLT 1.0 backwards-compatibility mode requires it: format-number('foo', '#') is the NaN symbol there, not an error.
FormatNumberArgStrict is the XPath 3.0 reading, where the same value is XPTY0004.
func FormatNumberArgStrict ¶ added in v1.1.0
FormatNumberArgStrict rejects a first argument that does not match the declared xs:numeric? parameter.
func FormatNumberString ¶ added in v1.1.0
func FormatNumberVersion ¶ added in v1.1.0
FormatNumberVersion is FormatNumber for a caller that knows the language version, which decides the error code for a malformed picture.
XSLT 2.0 raises XTDE1310 and XPath 3.0 raises FODF1310 for the same condition — the picture's syntax — so the code is a property of the caller rather than of the check. Every message is written with the XSLT code and rewritten here, since the two differ only in that prefix.
func FragmentIsValidXMLName ¶ added in v1.0.0
FragmentIsValidXMLName reports whether the fragment identifier in uri, if there is one, conforms to the rules for the XML media types.
XSLT 2.0 16.1 makes it a recoverable dynamic error (XTRE1160) if "the fragment identifier does not conform to the rules for fragment identifiers for that media type". For text/xml and application/xml those rules (RFC 7303) admit a bare name, which must be an XML Name, or an XPointer -- and an XPointer scheme part is itself a QName. So a fragment of "123456789" is not a legal one for XML however the resource is fetched, which is what lets the error be raised without retrieving anything: error-1160a names a w3.org URL this engine will not fetch at all, and diagnosing the fragment is the only way to reach the right answer offline.
It is exported because xslt/rtfuncs.go registers its own fn:document#1, which shadows the one here for arity 1 and needs the same rule.
A uri with no fragment, or an empty one, is not an error here: only a present and malformed fragment is.
func GenerateID ¶ added in v1.1.0
GenerateID returns the unique identifier fn:generate-id gives a node.
The spec requires only that it be stable for a node, distinct between nodes, and syntactically an XML name — so it is the node's document order index with a letter in front, which satisfies all three without a table.
Exported because the XSLT layer has had this function since 1.0 and must agree with this one: two spellings of the same identity would let generate-id() differ between a stylesheet and an expression over the same node.
func GroupingEqual ¶ added in v1.0.0
GroupingEqual reports whether two grouping key values are the same value under the "eq" operator, with the given collation comparing strings.
GroupingKey is the fast path for grouping: equal values hash alike, so a map finds the group in one lookup. It is not a complete answer, though, because the value comparison XSLT grouping uses is not transitive across the numeric types — erratum E25 spells this out. xs:float(1.0) equals xs:decimal(1.0000000000100000000001) (the decimal is promoted to float), and that decimal equals xs:double(1.00000000001) (promoted to double), yet the float and the double are different values. No single hash can express that, so a caller that missed in the map falls back to comparing against the key each existing group was opened with, in order.
A pair with no ordering at all — a string against a number — is simply not equal rather than an error, because grouping puts such values in separate groups rather than failing.
func GroupingKey ¶ added in v1.0.0
GroupingKey returns a string that is identical for two atomic values that compare equal, and different otherwise.
XSLT needs this for xsl:for-each-group, whose grouping keys are compared by value rather than by lexical form: xs:dateTime("2000-01-01T00:00:00Z") and xs:dateTime("2000-01-01T01:00:00+01:00") name the same instant and belong in one group, but their string forms differ. Keying on the string put them in two.
This is NOT xdm.MapKeyOf. Grouping applies the implicit timezone to an unzoned value, which is why the pair above group together; a map key does not, and same-key-013 through -015 require that pair to stay in separate entries. See the commentary on xdm.MapKeyOf for why the two must not be reconciled.
coll may be nil, in which case strings key on themselves.
func IsRelativeReference ¶ added in v1.1.0
IsRelativeReference is isRelativeRef for xslt, which registers its own fn:document#1 and needs the same judgement.
func NamespaceNodesOf ¶ added in v1.1.0
NamespaceNodesOf returns the nodes on n's namespace axis, which is every in-scope binding rather than only those declared on n itself.
The nodes are synthesized, as they are for a namespace:: step: the tree stores declarations, and the axis exposes the scope they accumulate to. It is exported for xsl:key, whose index walk has to visit the same nodes a pattern can match.
func OrderAtomics ¶ added in v1.2.0
OrderAtomics orders two atomic values the way a sorting host language needs to, returning -1, 0 or 1 and whether the pair is ordered at all.
XQuery's "order by" (section 3.10.6) and XSLT's xsl:sort both need a three-way answer, and the operators in this package give a two-way one: "lt" is a boolean, and deriving an order from a pair of boolean comparisons costs two harmonisations per comparison in a sort that already makes n log n of them. The rest of the pipeline — which type is promoted to which, how an untypedAtomic is treated, which pairs are ordered at all — is the value-comparison rule exactly, so this exposes that rule rather than restating it.
version is the language version the ordering is judged under, and it is a parameter rather than a constant because which pairs are ordered at all depends on it. F&O 3.0 section 11.1 enumerates the comparison operators on the binary types — "The following comparison operators on xs:base64Binary and xs:hexBinary values are defined" — and lists only op:hexBinary-equal and op:base64Binary-equal, so under 3.0 those types carry equality alone. 3.1 adds op:hexBinary-less-than and its siblings, which is what lets "order by" sort a sequence of them. rawCompare already draws that line; leaving Version at its zero value here silently put every caller on the wrong side of it, so a 3.1 "order by" over xs:hexBinary reported XPTY0004 while the very same values compared fine with "lt".
ok is false when the two types have no ordering between them (a string against a number), which the caller reports in whatever code its context requires: XPTY0004 for an ordering key, a separate group for grouping.
NaN is not special-cased here. A host that needs a position for it — which "order by" does, since it orders NaN with the empty sequence — decides that before calling, because the position depends on the clause's empty-order and not on the values.
func RegexpErr ¶ added in v1.0.0
RegexpErr reports a match-time failure from the most recent operation on re.
It is nil for an RE2 pattern, which cannot fail at match time, and it is the budget error for a backtracking pattern that ran out of steps.
func RegisterCollation ¶
RegisterCollation makes a collation available under a URI.
The spec requires exactly two collations — codepoint and the HTML ASCII case-insensitive one — and leaves the rest implementation-defined. This is how a host application supplies its own: a locale-aware comparison, or the case-blind collation the W3C test catalog defines for its own use.
Registering a URI that is already known replaces it, which is what makes a host override sensible. Registration is expected during setup, before any evaluation; it is guarded so that a late one cannot race a lookup, but it is not a way to change collations while expressions are running.
func RegisterEXSLTFuncs ¶ added in v1.0.0
func RegisterEXSLTFuncs(l *Library)
RegisterEXSLTFuncs adds the EXSLT common-module functions this processor implements to l.
Like RegisterXSLTFuncs and RegisterHarnessFuncs, these are deliberately NOT in Builtins(): EXSLT is an extension, and an XPath processor is required to report XPST0017 for a function it does not have. Registering into a chained Library keeps the populations separate, and — because function-available answers from the same library — it also makes function-available('exsl: node-set') report true exactly when the function is really callable.
Only node-set is provided. Every other EXSLT function is surface area that would then have to be supported, so they are added when something actually calls them, not speculatively.
func RegisterHarnessFuncs ¶ added in v1.0.0
func RegisterHarnessFuncs(l *Library)
RegisterHarnessFuncs adds the XPath 3.0 functions that the W3C conformance harness needs in order to SET UP a test, as distinct from the functions a stylesheet under test may call.
It exists for the same reason ParseExtended does, and observes the same boundary. Several XSLT test-set environments describe their initial context with an XPath 3.0 expression even when the stylesheet they then run is an XSLT 2.0 one — id-043's environment is
<source select="parse-xml('<root/>')" role="."/>
while id-043.xsl itself declares version="2.0". The setup expression is the harness's own XPath, not the test subject's, so it is written in the 3.0 language by design.
These functions are deliberately NOT in Builtins(). An XPath 2.0 processor is required to report XPST0017 for fn:parse-xml, and a stylesheet compiled against the builtin library still does, which is what the suite asserts elsewhere. Registering into a chained Library keeps the two populations separate in the same way RegisterXSLTFuncs does for the XSLT-only functions.
func RegisterXSLTFuncs ¶
func RegisterXSLTFuncs(l *Library)
RegisterXSLTFuncs adds the functions that XSLT 2.0 defines but XPath 2.0 does not.
fn:unparsed-text, fn:format-date and friends are in the XSLT specification, not the XPath one — a bare XPath 2.0 processor is required to report XPST0017 for them. This engine is an XSLT engine, so they must exist when a stylesheet is running, and must not when a plain XPath expression is being evaluated against the XPath library alone. Keeping them out of Builtins and adding them here is what makes both true.
func SerializeAdaptive ¶ added in v1.1.0
func SerializeAdaptive(seq xdm.Sequence, p SerializeParams) (string, error)
SerializeAdaptive renders a sequence with the adaptive output method of the same specification, section 10. See SerializeJSON for why it is exported.
func SerializeJSON ¶ added in v1.1.0
func SerializeJSON(seq xdm.Sequence, p SerializeParams) (string, error)
SerializeJSON renders a sequence with the JSON output method of the XSLT and XQuery Serialization 3.1 specification, section 4.
It exists so that xsl:result-document and xsl:output can offer method="json" without the xslt package reimplementing rules this package already applies for fn:serialize. The reverse dependency is not available — xpath cannot import xslt — and the two renderings must agree, since result-document-1401 and serialize-json-010 describe the same output by different routes.
func SetBacktrackingRegex ¶ added in v1.0.0
func SetBacktrackingRegex(on bool)
SetBacktrackingRegex turns the backtracking matcher on or off. See BacktrackingRegex.
It is safe to call while other goroutines are evaluating patterns: the setting is read atomically, and the compiled-pattern cache is keyed on it, so neither a stale compilation nor a torn read is possible. What is not guaranteed is which setting a call already in flight observes.
func TranslateSchemaRegexp ¶
TranslateSchemaRegexp rewrites an XML Schema regular expression into RE2 syntax, without anchoring it.
The XML Schema flavour and the XPath flavour share a grammar — Part 2 Appendix F defines the one, and XPath's fn:matches extends it — so the translation is the same in both directions: the multi-character escapes \i and \c, the block and category escapes, and character class subtraction, none of which RE2 accepts as written.
The result is deliberately unanchored, because the two flavours differ exactly there. fn:matches is a containment test, while a pattern facet must span the whole value. A caller using this for a pattern facet has to wrap the result — see the xsd package, which does so with \A(?:...)\z.
func TranslateSchemaRegexpVersion ¶
TranslateSchemaRegexpVersion is TranslateSchemaRegexp with the one grammar rule that XSD 1.1 changed made selectable.
1.1 stopped treating an unrecognised \p{Is...} block name as an error and began reading it as a class that matches every character, so the same pattern is invalid under 1.0 and valid under 1.1. reK88 asserts exactly that pair, which is why the version has to reach the grammar check.
Types ¶
type ArgumentPlaceholder ¶ added in v1.1.0
type ArgumentPlaceholder struct{}
ArgumentPlaceholder is the "?" of a partial function application, production [61]. It is never evaluated: a call whose argument list holds one yields a new function item rather than a result.
func (*ArgumentPlaceholder) Eval ¶ added in v1.1.0
func (e *ArgumentPlaceholder) Eval(_ *Context) (xdm.Sequence, error)
Eval implements Expr. A placeholder is never evaluated on its own: the call that contains it detects it first and builds a partial application instead.
func (*ArgumentPlaceholder) String ¶ added in v1.1.0
func (e *ArgumentPlaceholder) String() string
type ArrayConstructor ¶ added in v1.1.0
type ArrayConstructor struct {
Members []Expr
// Curly marks the "array { ... }" spelling.
Curly bool
}
ArrayConstructor is "array { ... }" or "[ ... ]", productions [70]-[72].
The two spellings differ in how they take their members, which is the whole point of having both: the square form makes one member per expression, so "[(1,2), 3]" has two members, while the curly form flattens whatever its single expression evaluates to, so "array { (1,2), 3 }" has three.
func (*ArrayConstructor) Eval ¶ added in v1.1.0
func (e *ArrayConstructor) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr.
func (*ArrayConstructor) String ¶ added in v1.1.0
func (e *ArrayConstructor) String() string
String implements Expr.
type Axis ¶
type Axis int
Axis identifies one of the thirteen XPath axes.
func (Axis) IsReverse ¶
IsReverse reports whether the axis is a reverse axis. Reverse axes number their positions backwards, which changes what position() means inside a predicate — the one place the distinction is observable.
func (Axis) PrincipalKind ¶
PrincipalKind is the node kind an axis selects when the node test is a name or wildcard: attributes on the attribute axis, namespaces on the namespace axis, elements everywhere else.
type BinaryOp ¶
type BinaryOp struct {
Op string
Left, Right Expr
// ResolveQName binds a prefix in the static context of this operator, for
// the one conversion that needs it. A general comparison casts an
// untypedAtomic operand to the *other* operand's type, and when that type
// is xs:QName the lexical form carries a prefix whose namespace lives in
// the static context -- which the runtime Context deliberately does not
// carry, since namespaces are a static property. Capturing the resolver
// on the node is what makes the binding available where the cast happens.
// Nil for every operator other than a comparison, and for a comparison
// parsed without a namespace resolver.
ResolveQName func(prefix string) (string, bool)
}
BinaryOp is any infix operator. Keeping them in one node with an Op field rather than one type per operator keeps the parser's precedence ladder short and puts all the operand-conversion rules in one evaluator function, which is where they are easiest to check against the spec's tables.
type Binding ¶
Binding is one "$var in expr" clause of a for or quantified expression, or one "$var := expr" clause of a let expression.
type CastExpr ¶
type CastExpr struct {
Operand Expr
Type SequenceType
Castable bool // true for "castable as", which yields a boolean
}
CastExpr is "expr cast as type" and "expr castable as type".
type Collation ¶
type Collation interface {
Compare(a, b string) int
Contains(s, sub string) bool
StartsWith(s, prefix string) bool
EndsWith(s, suffix string) bool
IndexOf(s, sub string) int
}
Collation compares two strings. Only the operations XPath actually needs are exposed, because a general Compare is not enough: fn:contains under a case-insensitive collation is not "compare the folded strings", it is "does the folded needle occur in the folded haystack".
func ResolveCollation ¶
ResolveCollation returns the collation a URI names.
A relative URI is accepted when its tail matches a known collation, because the QT3 suite and some stylesheets write "collation/codepoint" rather than the full URI. Resolving it against the static base URI would be more correct still, but the base is not threaded into every function that takes a collation argument, and matching the tail covers the forms that occur.
type CollectionResolver ¶
type CollectionResolver interface {
// ResolveCollection returns the documents in uri, resolved against base.
//
// The result is a sequence rather than a []*xdm.Tree because a collection
// is permitted to contain items that are not document nodes.
ResolveCollection(uri, base string) (xdm.Sequence, error)
}
CollectionResolver loads a named set of documents for fn:collection.
It is deliberately separate from DocumentResolver rather than an extra method on it. A caller who wants fn:doc for the code lists shipped beside a stylesheet does not thereby want fn:collection to enumerate a directory, and folding the two together would make enabling one enable the other.
The empty uri is the default collection — fn:collection() with no argument. A resolver that has no default should return an error for it rather than an empty sequence, for the reason given on fnCollection.
type CompileOptions ¶ added in v1.3.0
type CompileOptions struct {
// Namespaces resolves the prefixes in src. Nil admits none, which is
// what passing a nil NamespaceResolver does.
Namespaces NamespaceResolver
// Version is the language version. The zero value is XPath20.
Version Version
// RefFloor raises the version at which a named function reference is
// admitted, for a host whose own version outruns the expression's. Zero
// means Version; see refversion.go.
RefFloor Version
// XQuery parses src by the rule an expression embedded in an XQuery
// module follows; see ParseXQuery for the one difference.
XQuery bool
// Context bounds the compile. Nil means no deadline.
//
// Cancellation is observed before parsing, between parsing and
// optimisation, and periodically inside the optimiser -- so a deadline
// is honoured at a granularity rather than instantly, and an expression
// compiling in microseconds (the ordinary case: the median is ~3µs)
// never observes it at all.
//
// Parsing has no cancellation of its own and is roughly two thirds of
// the cost on a large expression, so a deadline set to expire mid-compile
// is observed when parsing finishes rather than during it. MaxBytes is
// the bound that covers parsing.
Context context.Context
// MaxBytes bounds len(src). Zero means unbounded. It is checked before
// parsing, so an over-large expression costs the comparison and nothing
// else.
//
// This is the deterministic half of the protection Context gives: it
// refuses the same input every time, where a deadline depends on how
// loaded the machine is. A host compiling expressions taken from
// document data -- xsl:evaluate does exactly that, at transform time --
// should set it.
MaxBytes int
}
CompileOptions configures CompileWith.
The zero value compiles XPath 2.0 with no namespace resolver, no deadline and no size bound, which is what Compile(src, nil) does. Version in particular is XPath20 when unset, matching the zero value of Version itself and of Context.Version, so an unset version means the same thing everywhere in this package.
An unset Version is safe to get wrong in one direction only: 3.0 and 3.1 syntax is REFUSED by the 2.0 grammar rather than silently mis-parsed, so a host that forgets to set it sees a parse error at the call site rather than a wrong answer later. A 3.1 host must still set it.
Fields added here in future are additive: a zero value must always mean the behaviour this package had before that field existed.
type Compiled ¶
type Compiled struct {
// contains filtered or unexported fields
}
Compiled is a parsed XPath expression, ready to evaluate against any context.
Compiling once and evaluating many times is the intended usage: parsing dominates the cost of a short expression, and a stylesheet evaluates the same expression once per node. A Compiled value is immutable and safe for concurrent use.
func Compile ¶
func Compile(src string, ns NamespaceResolver) (*Compiled, error)
Compile parses src, resolving namespace prefixes with ns.
It is CompileWith with only Namespaces set, and so compiles XPath 2.0. A caller that needs a deadline or a size bound calls CompileWith.
func CompileVersion
deprecated
added in
v1.1.0
func CompileVersion(src string, ns NamespaceResolver, v Version) (*Compiled, error)
CompileVersion is Compile for a given version of the language.
Compile remains the 2.0 spelling so that an existing caller keeps the behaviour it had; a 3.0 host calls this instead. The version is recorded on the result, so evaluating it does not require the caller to set it on the context as well.
Deprecated: use CompileWith with CompileOptions.Version set.
func CompileVersionRefFloor
deprecated
added in
v1.1.0
func CompileVersionRefFloor(src string, ns NamespaceResolver, v, refFloor Version) (*Compiled, error)
CompileVersionRefFloor is CompileVersion with the named-function-reference floor raised; see ParseVersionRefFloor and refversion.go.
Deprecated: use CompileWith with CompileOptions.RefFloor set.
func CompileWith ¶ added in v1.3.0
func CompileWith(src string, opts CompileOptions) (*Compiled, error)
CompileWith parses src according to opts and optimises the result.
It is the entry point the other Compile functions delegate to; they remain the spellings for a caller that needs neither bound, and this one is where options added later appear without another positional spelling.
Optimisation happens once per compiled expression, and a compiled stylesheet is reused across every node and every document, so anything folded here is work removed from the inner loop rather than deferred.
func CompileXQuery
deprecated
added in
v1.2.1
func CompileXQuery(src string, ns NamespaceResolver, v Version) (*Compiled, error)
CompileXQuery is CompileVersion for an expression taken from an XQuery module; see ParseXQuery for the one rule that differs.
Deprecated: use CompileWith with CompileOptions.XQuery set.
func MustCompile ¶
func MustCompile(src string, ns NamespaceResolver) *Compiled
MustCompile is Compile, panicking on error. For tests and for expressions that are literals in this package's own source.
func (*Compiled) CompatMode ¶ added in v1.0.0
CompatMode reports whether c evaluates under XPath 1.0 compatibility mode.
func (*Compiled) EvalString ¶
EvalString evaluates and returns the string value of the result, which is the concatenation rule of fn:string applied to the first item, or "" for the empty sequence.
func (*Compiled) Expr ¶
Expr returns the root of the AST, for callers that need to inspect or rewrite it (the XSLT layer analyses patterns this way).
func (*Compiled) FreeVariables ¶ added in v1.2.0
FreeVariables reports every variable this expression reads without binding.
It is the variable half of StaticCalls, and exists for the same reason: variables resolve at evaluation time here, so XPST0008 — a static error — is only raised for a reference something actually evaluates. A host that has to report it at compile time collects the names from here and checks them against what it knows is in scope.
A name is free when no enclosing "for", "let", "some", "every" or inline function binds it. That is what makes the answer usable as an error rather than as a hint: "let $b := $a return $b" reports $a and not $b, where a lexical scan of the same text cannot tell the two apart.
The order is the order of first occurrence, so that a caller reporting one name reports the leftmost.
func (*Compiled) StaticCalls ¶ added in v1.1.0
func (c *Compiled) StaticCalls() []StaticCall
StaticCalls reports every statically named function this expression calls or references, at every depth.
Function resolution in this engine happens at evaluation time, which is what lets a stylesheet's own xsl:function declarations be visible without a separate binding pass. The cost is that XPST0017 -- a *static* error -- is only raised for a call that is actually evaluated, and a great deal of a stylesheet never is: an unreferenced variable, a template never matched. A host that has to report the error at compile time collects the names from here and resolves them itself once every declaration is in.
Nothing is filtered: names in every namespace are reported, including ones the host will want to excuse. It cannot be decided here, because which functions exist is a property of the host's library and not of the grammar.
func (*Compiled) WithCompatMode ¶ added in v1.0.0
WithCompatMode returns a copy of c evaluated under XPath 1.0 compatibility mode.
The mode is static, exactly as the base URI and the default collation are: XSLT 3.8 fixes it from the [xsl:]version attribute of the nearest ancestor-or-self of the element the expression is written on, which cannot change between evaluations. Binding it to the compiled expression rather than threading it through the dynamic context is therefore both correct and what keeps an ordinary 2.0 expression byte-identical to what it was: a Compiled that was never given the flag never sets it on the context, so no evaluation outside a 1.0 scope can observe it.
func (*Compiled) WithDefaultCollation ¶ added in v1.0.0
WithDefaultCollation returns a copy of c whose functions use coll when no collation argument is given.
func (*Compiled) WithDefaultCollationURI ¶ added in v1.3.0
WithDefaultCollationURI is WithDefaultCollation that also records the URI that named coll, which is what fn:default-collation reports. A caller that resolved a URI to get coll should use this, because the URI cannot be recovered from the Collation value afterwards.
func (*Compiled) WithStaticBaseURI ¶ added in v1.0.0
WithStaticBaseURI returns a copy of c whose expressions resolve relative references against base.
It exists because the static base URI really is static: xml:base is written in the stylesheet and cannot change between evaluations, so binding it to the compiled expression is both correct and cheaper than threading it through the dynamic context.
func (*Compiled) WithStaticHost ¶ added in v1.1.0
WithStaticHost attaches an opaque host-language value to the expression, which Eval puts in Context.StaticHost. See Compiled.staticHost.
type Context ¶
type Context struct {
// Item is the context item. It is nil where there is no context item,
// which is an error to reference rather than an empty sequence.
Item xdm.Item
// Position is the context position, 1-based. Zero means "no focus".
Position int
// Size is the context size.
Size int
// Vars holds in-scope variable bindings, keyed by expanded name.
// Lookups walk to Parent, so a nested scope does not copy the map.
Vars map[string]xdm.Sequence
Parent *Context
// Funcs resolves function calls. Supplied by the caller so that XSLT can
// add xsl:function declarations and extension functions without this
// package knowing about them.
Funcs FunctionLibrary
// Version is the language version the expression was compiled under.
//
// It reaches the function library because a few functions differ between
// versions in ways the parser cannot settle: fn:matches and its siblings
// accept the "q" flag and the 3.0 regular expression constructs only
// under 3.0, and must raise the same errors as any other processor when
// asked to be 2.0. The zero value is XPath20, so a Context built by an
// existing caller behaves exactly as it did before.
Version Version
// RegexVersion raises the version of the *regular expression* dialect
// above Version, without admitting any other 3.0 construct.
//
// The two are separable because the regex language is not part of the
// XPath grammar: a pattern is a string, read by fn:matches and its
// siblings at the point of call rather than by the parser. So a host may
// legitimately want a 2.0 expression to accept a 3.0 pattern, which is
// exactly what XSLT needs -- the XSLT suite runs version="2.0"
// stylesheets under a 3.0 processor and expects "(?:...)" to compile,
// because the dialect follows the processor while the syntax follows the
// module.
//
// The zero value adds nothing: the effective dialect is the larger of
// this and Version, so an existing caller is unaffected.
RegexVersion Version
// LibraryVersion raises the version of the *function library* above
// Version, without admitting any new syntax.
//
// Which functions exist is a property of the processor rather than of the
// module, in the same way the regular-expression dialect is: calling a
// function is ordinary syntax at every version, and only the name has to
// resolve. The XSLT suite requires the separation — accessor-050 and
// fifteen others are version="2.0" stylesheets scoped XSLT30+ that call
// fn:path, and a 3.0 processor must find it for them.
//
// Raising Version instead would also hand those modules inline functions
// and map constructors, which the XSLT 2.0 grammar must refuse.
//
// The zero value adds nothing: the effective floor is the larger of this
// and Version, so an existing caller is unaffected.
LibraryVersion Version
// StaticBaseURI is the base URI of the expression itself — the stylesheet
// or query it was written in — which is what fn:static-base-uri returns
// and what fn:resolve-uri resolves against by default.
//
// It is distinct from a *node's* base URI, which comes from the document
// the node was parsed from. Returning the context node's was the nearest
// thing available before this existed, and it is a different value: a
// stylesheet in one place can perfectly well be applied to a document
// from another.
StaticBaseURI string
// QualifyVar lets the host language redirect a variable reference to a
// different name; see VarQualifier. Nil for the flat scoping XPath's own
// grammar implies.
QualifyVar VarQualifier
// MissingVar lets the host language say what an unresolved reference
// means. Returning nil leaves the ordinary XPST0008. It exists because a
// host may decline to bind a variable whose evaluation failed, and owe
// the failure to whoever refers to it -- an XSLT 3.0 abstract variable
// is the case.
MissingVar func(ctx *Context, name xdm.QName) error
// StaticHost is an opaque value the host language attached to the
// expression being evaluated; see Compiled.WithStaticHost. This package
// never interprets it, only carries it.
StaticHost any
// StaticNamespaces is the statically known namespaces of the expression,
// carried from compile time so that a function can expand a prefix that
// reaches it as a *string* rather than as syntax.
//
// Almost every prefix in an expression is resolved by the parser, which is
// why NamespaceResolver is a compile-time interface. The exception is a
// prefixed name that arrives as an argument value: F&O 9.8.4.3 says the
// $calendar argument of the date formatting functions "must be a valid
// EQName ... if it is a lexical QName then it is expanded into an expanded
// QName using the statically known namespaces", and the functions' own
// Properties section lists them as depending on "namespaces" for exactly
// this reason. The argument need not be a literal, so the expansion cannot
// be done at parse time; the resolver has to survive into evaluation.
//
// Nil means the caller compiled without one, and a prefixed calendar is
// then unresolvable — which is the same answer an empty resolver gives.
StaticNamespaces NamespaceResolver
// ImplicitTimezone is the offset in minutes applied to date/time values
// that carry no timezone. The spec requires the dynamic context to supply
// one; defaulting to UTC keeps results reproducible across machines,
// which matters more for a validator than matching local time.
ImplicitTimezone int
// Ctx carries cancellation. A stylesheet can loop for a long time on
// pathological input, and the caller needs a way out that does not
// involve killing the process.
Ctx context.Context
// Docs resolves fn:doc and fn:document URIs. Nil disables them, which is
// the safe default: a stylesheet that can open arbitrary URIs is an SSRF
// and file-disclosure vector.
Docs DocumentResolver
// Collections resolves fn:collection URIs. Nil disables it, for the same
// reason nil disables Docs, and setting Docs does not set this: see
// CollectionResolver.
Collections CollectionResolver
// Texts resolves fn:unparsed-text URIs. Nil disables it, and setting
// Docs does not set this: reading a file as raw text is a wider grant
// than reading it as a parsed document. See TextResolver.
Texts TextResolver
// Entities resolves the external entities and external DTD subset that a
// document handed to fn:parse-xml declares. Nil refuses every one of
// them, which is the safe default and the one nearly every caller wants:
// parse-xml is handed a string that came from somewhere, and honouring
// <!ENTITY e SYSTEM "..."> inside it is XXE by definition. Setting Docs
// or Texts does not set this — those grant reads of URIs the expression
// itself named, while this grants reads of URIs the *parsed data* names,
// which is a different and wider trust decision.
//
// Confinement is entirely the resolver's; see xdm.EntityResolver.
Entities xdm.EntityResolver
// Environment answers fn:environment-variable and
// fn:available-environment-variables. Nil withholds the process
// environment from both, which is the default and the safe one: the
// environment of a server process routinely holds credentials, and
// nothing about evaluating an expression implies consent to read them.
//
// Setting Docs or Texts does not set this, and this does not set those:
// those grant reads of a URI space the caller has confined, while this
// grants reads of the process's own state, which no resolver root
// bounds. Withholding costs no conformance — see EnvironmentResolver.
Environment EnvironmentResolver
// Validator validates a tree fn:json-to-xml has just built, when the
// call asked for validate=true. Nil means the processor cannot do it,
// which is FOJS0004 rather than a silent untyped result; see
// TreeValidator.
Validator TreeValidator
// Compat is XPath 1.0 compatibility mode, which XSLT 3.8 puts in force for
// expressions written on an element whose effective [xsl:]version is below
// 2.0. Under it the coercion rules of XPath 2.0 appendix B.1 apply: a
// multi-item argument to a parameter expecting a string, a number or a
// node is truncated to its first item instead of raising XPTY0004,
// arithmetic on a non-numeric operand yields NaN rather than a type error,
// and a general comparison converts its operands the way XPath 1.0 did.
//
// It defaults to false and is set only by a Compiled that was given it, so
// ordinary 2.0 evaluation never sees it.
Compat bool
// MapDuplicateCode overrides the error code raised when a map constructor
// names the same key twice.
//
// The construct is one expression with two spellings of the same failure,
// because the code is the host language's rather than XPath's. XQuery 3.1
// section 3.11.1 calls it XQDY0137, which is the default and what the QT3
// suite requires. XSLT 3.0 section 17.4 says of the very same MapExpr that
// "if two or more entries have the same key then a dynamic error occurs
// [see ERR XTDE3365]", so an XSLT host sets this to XTDE3365 -- matching
// the code xsl:map already raises for a duplicate, which is the point: in
// XSLT the two ways of writing a map agree on how they fail.
//
// The zero value keeps XQDY0137, so a host that does not set it behaves
// exactly as it did.
MapDuplicateCode string
// Depth guards against unbounded recursion in user-defined functions and
// named templates, which the spec does not bound.
Depth int
// MaxDepth is the bound Depth is checked against. Zero means the package
// default, MaxDepth.
//
// It is settable because the default is a guard against untrusted input
// rather than a limit the language imposes: a query that recurses five
// thousand deep is perfectly legal, and fn-format-number's numberformat121
// and 122 do exactly that on purpose. A caller evaluating an expression it
// trusts can raise the bound; one evaluating an expression from outside
// should leave it alone.
MaxDepth int
// Now is the value fn:current-dateTime and its siblings return.
//
// The spec requires these to be stable for the whole of one evaluation:
// calling current-dateTime() twice must give the same answer, or a
// stylesheet that stamps a document and then checks the stamp against
// "now" can disagree with itself. Reading the clock here once, rather
// than per call, is what guarantees that. A zero value means the caller
// did not set one and the functions are unavailable.
Now time.Time
// HasNow distinguishes an unset clock from a legitimately zero time.
HasNow bool
// contains filtered or unexported fields
}
Context is the XPath dynamic context: everything an expression can observe beyond its own AST.
The focus (item, position, size) changes on every step and predicate, while the rest (variables, functions, the implicit timezone) changes rarely. They are kept in one struct anyway, copied cheaply by value in the hot paths, because splitting them means every evaluator function takes two parameters and the copy is a handful of words either way.
func NewContext ¶
func NewContext(item xdm.Item, funcs FunctionLibrary) *Context
NewContext returns a context with the given focus and library.
func (*Context) AdoptBudget ¶ added in v1.3.0
AdoptBudget returns a copy of c spending src's item and byte allowances instead of its own, so that a nested evaluation continues its caller's budget rather than being granted a fresh one.
It exists for a host language that starts a whole new evaluation inside an existing one and cannot simply pass the caller's Context down. XSLT's fn:transform is the case: the nested transformation builds its own runtime, and newRuntime calls NewContext, which mints both counters from scratch -- so every level of a nest got the full MaxItems and MaxBytes over again while the depth budget correctly inherited. The house rule the depth budget already follows is that a budget is monotonic: a nested evaluation may spend the parent's remaining allowance, never reset it.
Each counter is carried WITH its held flag, never without. The flag is what says where the budget's boundary is, and a counter forwarded without it would be reset by Compiled.Eval once per expression in the nested evaluation -- which would clear the CALLER's accumulated charges through the shared pointer and hand the caller an allowance it has already spent. That is the same leak HoldItemBudget's and HoldByteBudget's idempotence guards exist to prevent, arriving by another route, and it would be worse than the fresh allowance it replaced.
A nil src, or a src with no budget, leaves c's own budget alone: a caller with nothing to inherit from is a fresh root, which is what a top-level evaluation legitimately is.
func (*Context) ChargeBytes ¶ added in v1.3.0
ChargeBytes charges n bytes of built string content against the evaluation budget, reporting XPDY0130 when the budget is exhausted.
It is exported for a host language that concatenates in its own evaluator rather than through this package's Expr tree. XSLT is the case: xsl:value-of joins its selected sequence with xslt's own code, so the text it appends reaches none of the functions here that charge as they grow.
func (*Context) ChargeItems ¶ added in v1.3.0
ChargeItems charges n items against the evaluation budget, reporting XPDY0130 when the budget is exhausted.
It is exported for a host language that accumulates sequences in its own evaluator rather than through this package's Expr tree. XQuery's FLWOR is the case: §3.10 defines it over a materialised tuple stream, which xquery.flwor builds itself, so none of the accumulation reaches the constructs in this package that charge as they grow. Such a host must also hold the budget across the whole of its evaluation — see HoldItemBudget — or the reset in Compiled.Eval clears the counter under it once per iteration.
func (*Context) ChargeNodes ¶ added in v1.3.0
ChargeNodes charges n constructed result-tree nodes against the evaluation budget, reporting XPDY0130 when the budget is exhausted.
It is exported because the construction happens in xdmbuild, which names neither host language and imports neither this package nor any other beyond xdm. A host passes the charge in through xdmbuild.Policy instead, which is already the seam for everything the builder cannot know by itself.
func (*Context) ContextNode ¶
ContextNode returns the context item as a node, or an error when there is no context item or it is an atomic value.
Steps require a node context; the distinct error codes matter because XPDY0002 (absent) and XPTY0020 (present but not a node) mean different things to a stylesheet author.
func (*Context) Descend ¶
Descend returns a copy with the recursion depth incremented, erroring past the limit.
func (*Context) EntityBudget ¶ added in v1.3.0
func (c *Context) EntityBudget() *xdm.EntityBudget
EntityBudget returns the entity-expansion allowance shared by every parse this evaluation performs, for a host that parses on the evaluation's behalf rather than through fn:parse-xml.
A nil result means this Context carries no allowance -- a hand-built one -- and the parse gets the ordinary per-document ceiling.
func (*Context) HoldByteBudget ¶ added in v1.3.0
HoldByteBudget returns a copy of c on which Compiled.Eval will not reset the byte budget, and arms a fresh budget for the construction about to begin.
Compiled.Eval resets per expression because that is the right boundary for a bare XPath expression. A host that builds one result out of many expressions has the opposite problem: a query's "let" chain and a template's run of xsl:variable declarations each reach xpath once per binding, so the per-expression reset clears the counter between the doublings and a chain that doubles its result per line is never charged for the doubling. Holding it moves the boundary out to one query evaluation or one transform, which is where "how much string content must fit in memory at once" is actually asked.
The flag rides on the value copy the scope-changing methods make, so every nested evaluation inherits the hold while the caller's own Context keeps the per-expression boundary it had. A context that already holds the budget is returned unchanged rather than re-armed: an inner construction that reset the counter would clear the outer one's charges and hand it an allowance it has already spent, which is the leak this exists to avoid arriving from the other side.
func (*Context) HoldItemBudget ¶ added in v1.3.0
HoldItemBudget returns a copy of c on which Compiled.Eval will not reset the item budget, and arms a fresh budget for the evaluation about to begin.
Compiled.Eval resets per expression because that is the right boundary for XPath and for XSLT, where the host evaluates one expression per node and a budget carried across all of them would refuse a legitimate transform. A host whose own evaluator loops over expressions has the opposite problem: a FLWOR calls Compiled.Eval once per tuple, so the per-expression reset clears the counter two million times and the budget never binds. Holding it moves the boundary out to the host's evaluation, which is where "how large may one evaluation's intermediate sequences grow" is actually asked.
The flag rides on the value copy the scope-changing methods make — Descend, WithVar, WithFocus — so every nested evaluation inherits the hold, while the caller's own Context keeps the per-expression boundary it had. The counter itself is shared through the same pointer, so the hold measures the whole tree of nested evaluations against one allowance. A context that already holds the budget is returned unchanged rather than re-armed. Nothing calls it that way today, but an inner evaluation that reset the counter would clear the outer one's charges and hand the outer evaluation an allowance it has already spent — the leak this whole change exists to avoid, arriving from the other side.
func (*Context) LookupVar ¶
LookupVar resolves a variable by expanded name, walking enclosing scopes.
func (*Context) WithFocus ¶
WithFocus returns a copy of ctx with a new context item, position and size, sharing the variable scope.
This is the operation performed once per node per step. It copies the struct rather than allocating a child scope, so variable lookups still resolve through the same maps without a new one being built.
The copy itself does allocate — it is the largest single allocation site in the engine, around a quarter of what a stylesheet render allocates. Reusing one context across a step loop was measured and made no difference at all (4,963,596 vs 4,964,187 bytes per render), so it was reverted: WithVar builds children holding a pointer back to this context, and the aliasing risk that reuse introduces buys nothing. Anyone tempted to try it again should measure first.
func (*Context) WithVar ¶
WithVar returns a child context binding name to val.
A child scope with its own one-entry map is used rather than mutating the parent's, because a for-expression binds a fresh value per iteration while the body may capture it; mutation would make all iterations observe the last value.
type ContextCollectionResolver ¶ added in v1.1.0
type ContextCollectionResolver interface {
CollectionResolver
ResolveCollectionIn(ctx *Context, uri, base string) (xdm.Sequence, error)
}
ContextCollectionResolver is a CollectionResolver that also sees the evaluation context of the fn:collection call.
It mirrors ContextDocumentResolver and exists for the same reason: XSLT 4.4 scopes xsl:strip-space to the package the call appears in LEXICALLY -- "Declarations within a library package only affect the handling of documents loaded using a call on the document, doc, or collection functions ... appearing lexically within the same package" -- and the context is what carries the package. A resolver that does not implement this is called through ResolveCollection as before.
type ContextDocumentResolver ¶ added in v1.1.0
type ContextDocumentResolver interface {
DocumentResolver
// ResolveDocumentIn is ResolveDocument for a call made from ctx.
ResolveDocumentIn(ctx *Context, uri, base string) (*xdm.Tree, error)
}
ContextDocumentResolver is a DocumentResolver that also wants the evaluation context of the call.
It is a separate optional interface rather than an extra parameter on ResolveDocument so that existing implementations keep working: a resolver that does not implement it is called through ResolveDocument exactly as before. fn:doc and fn:document prefer this method where it is offered.
XSLT needs it because whitespace stripping is scoped to the package the CALL is written in -- section 4.4 of that specification -- so which declarations apply is a property of the expression rather than of the transform, and only the context carries it.
type ContextItem ¶
type ContextItem struct{}
ContextItem is the "." expression.
func (*ContextItem) Eval ¶
func (e *ContextItem) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr for the context item.
func (*ContextItem) String ¶
func (e *ContextItem) String() string
type DecimalFormat ¶ added in v1.1.0
type DecimalFormat struct {
Name xdm.QName
DecimalSeparator rune
GroupingSeparator rune
Percent rune
PerMille rune
ZeroDigit rune
Digit rune
PatternSeparator rune
MinusSign rune
Infinity string
NaN string
// ExponentSeparator is the character that introduces the exponent part of
// a picture, which XPath 3.1 added along with scientific notation itself.
// It is a declared symbol like every other one here because a locale that
// writes 1,2346E4 needs to say so; the default "e" is what an undeclared
// format uses.
ExponentSeparator rune
}
Every symbol is configurable because the instruction exists to serve locales: a German invoice writes 1.234,56 where an English one writes 1,234.56, and the picture string is written once against whatever symbols the format declares.
func DefaultDecimalFormat ¶ added in v1.1.0
func DefaultDecimalFormat() *DecimalFormat
DefaultDecimalFormat returns the format used when none is declared.
type DocumentResolver ¶
type DocumentResolver interface {
// ResolveDocument returns the tree for uri, resolved against base.
ResolveDocument(uri, base string) (*xdm.Tree, error)
}
DocumentResolver loads a document by URI for fn:doc and fn:document.
type DynamicCall ¶ added in v1.1.0
DynamicCall is "$f(1, 2)": a call on the function item an expression produces, rather than on a statically named function.
It is the ArgumentList half of production [48], PostfixExpr ::= PrimaryExpr (Predicate | ArgumentList)*, which is why it wraps an arbitrary expression rather than a name.
func (*DynamicCall) Eval ¶ added in v1.1.0
func (e *DynamicCall) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr: it calls the function item the target produces.
func (*DynamicCall) String ¶ added in v1.1.0
func (e *DynamicCall) String() string
type DynamicFunctionLibrary ¶ added in v1.1.0
type DynamicFunctionLibrary interface {
FunctionLibrary
// LookupDynamic returns the function a dynamic reference to this name and
// arity resolves to.
LookupDynamic(ctx *Context, name xdm.QName, arity int) (Function, bool)
}
DynamicFunctionLibrary is a FunctionLibrary that answers a DYNAMIC function reference -- fn:function-lookup and fn:function-available, where the name is a value rather than a literal -- differently from a call written out in the source.
A host language may scope the two differently. XSLT 3.0 3.6.3.5 does: a dynamic reference sees only the functions declared in the package the call is written in, where an ordinary call resolves against the whole assembled stylesheet. The context is passed because the package is a property of the expression, carried on Context.StaticHost.
A library that does not implement this is scoped identically either way, which is what XPath on its own means.
type EnvironmentResolver ¶ added in v1.3.0
type EnvironmentResolver interface {
// LookupEnvironment returns the value of name and whether it is
// available. A resolver that hides a variable returns ok false, which is
// the same answer an unset variable gives.
LookupEnvironment(name string) (value string, ok bool)
// EnvironmentNames returns the names LookupEnvironment will answer, in
// any order. An empty result is legal and means no variable is exposed.
EnvironmentNames() []string
}
EnvironmentResolver answers fn:environment-variable and fn:available-environment-variables. Nil disables both, which is the default and the safe one: the process environment routinely holds credentials, and nothing about running a stylesheet implies consent to read them.
It is an interface rather than a bool for the same reason the other resource gates are. A caller who wants these functions to work usually wants a *chosen* set of variables visible, not the whole process environment — the grant is which names, not merely on or off. OSEnvironment is the widest implementation and has to be asked for by name.
Both methods are answerable as the empty result, and that is what makes the gate conformance-safe: F&O 3.1 section 14.6.9 makes it implementation-dependent which variables are available, and section 14.6.8 returns the empty sequence for a name that is not among them. So a withheld variable and an unset one are indistinguishable by design, and a stylesheet cannot tell the gate from a bare environment.
type Expr ¶
type Expr interface {
// Eval evaluates the expression in ctx and returns a sequence.
Eval(ctx *Context) (xdm.Sequence, error)
// String returns a source-like rendering, used in error messages and to
// make test failures readable.
String() string
}
Expr is a node in the XPath abstract syntax tree.
Evaluation is a method on the AST rather than a separate visitor. XPath evaluation is a simple recursive walk with no multi-pass analysis, so a visitor would add an indirection layer without buying anything; the one place a second pass would help (static typing) is not implemented, and the spec permits a dynamically-typed implementation.
func Parse ¶
func Parse(src string, ns NamespaceResolver) (Expr, error)
Parse compiles an XPath 2.0 expression.
func ParseExtended ¶ added in v1.0.0
func ParseExtended(src string, ns NamespaceResolver) (Expr, error)
ParseExtended compiles an expression in which the XPath 3.0 braced URI literal Q{uri}local is also accepted.
A stylesheet compiled with Parse still rejects it, which is what a 2.0 processor must do. It exists for a caller that is itself writing XPath rather than running someone else's — specifically the conformance harness, whose assertion expressions are written in the 3.0 language even for tests whose stylesheets are 2.0.
The simple map operator "!" used to be gated here too. It is now accepted unconditionally, along with "||" and "=>": see Lexer.extended.
func ParseVersion ¶ added in v1.1.0
func ParseVersion(src string, ns NamespaceResolver, v Version) (Expr, error)
ParseVersion compiles an expression in the given version of the language.
Parse remains the 2.0 spelling, so an existing caller is unaffected.
func ParseVersionRefFloor ¶ added in v1.1.0
func ParseVersionRefFloor(src string, ns NamespaceResolver, v, refFloor Version) (Expr, error)
ParseVersionRefFloor is ParseVersion with the named-function-reference floor raised: "#N" is accepted even when v is below 3.0.
The floor exists because which functions exist -- and so whether a name can be referenced at all -- follows the processor rather than the module, in the same way Context.LibraryVersion and Context.RegexVersion already do. See refversion.go.
func ParseXQuery ¶ added in v1.2.1
func ParseXQuery(src string, ns NamespaceResolver, v Version) (Expr, error)
ParseXQuery is ParseVersion for an expression taken from an XQuery module.
It differs from ParseVersion in one rule. XQuery's RelativePathExpr may begin with a direct constructor and XPath's may not, so the two languages disagree about whether "<" can be the first token of a step — which is what xgc:leading-lone-slash consults to decide whether a "/" is a whole expression or the head of a path. See Parser.xquery and startsStep.
type FilterExpr ¶
FilterExpr applies predicates to an arbitrary expression, as in "(1 to 10)[. mod 2 = 0]".
func (*FilterExpr) Eval ¶
func (e *FilterExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr for a filtered expression.
func (*FilterExpr) String ¶
func (e *FilterExpr) String() string
type ForExpr ¶
ForExpr is "for $x in seq return expr".
type FuncCall ¶
FuncCall is a function call. Resolution happens at evaluation time against the context's function library, so that a stylesheet's own xsl:function declarations are visible without a separate binding pass.
type Function ¶
type Function struct {
Name xdm.QName
Arity int
// Call receives the already-evaluated arguments. Functions that need the
// context item (fn:string with no argument, fn:position) read it from ctx.
Call func(ctx *Context, args []xdm.Sequence) (xdm.Sequence, error)
// Since is the first language version in which this function exists. The
// zero value is XPath20, so every function that predates versioning is
// available everywhere, and a 3.0 addition is invisible to a 2.0
// expression rather than being quietly callable from one.
//
// The check belongs at lookup rather than in each function body: a 2.0
// expression calling fn:head must get "unknown function", the same static
// error every other processor raises, not a working answer or a distinct
// complaint from inside a function it should not have found.
//
// It applies only to the fn: namespace in practice. The math: functions
// are gated by their namespace instead — see registerMathFuncs.
Since Version
// Signature is the declared return type followed by the parameter types,
// in source spelling. It is what a typed function test — "f#1 instance of
// function(element(A)) as xs:string" — is judged against.
//
// applyBuiltinSignatures fills this from specSignatures for every
// function in the four namespaces the F&O manifest covers, so it is nil
// only for a function with no declared type to read: a host or EXSLT
// extension, or a stylesheet's own. Such a function is matched on arity
// alone, which is the right answer there rather than merely the
// permissive one -- its declared type is whatever declared it, not
// "nothing".
Signature []string
// VariadicSignature carries a variadic function's declared type without
// repeating its one parameter, and mirrors the field of the same name on
// xdm.FunctionItem -- see the commentary there for why the materialised
// form is a liability rather than a convenience. Nil for every
// fixed-arity function, which leaves Signature the ordinary path.
VariadicSignature *xdm.VariadicSignature
}
Function is a callable XPath function.
func LookupDynamic ¶ added in v1.1.0
LookupDynamic resolves a DYNAMIC function reference -- one whose name is a value rather than a literal, as in fn:function-lookup and fn:function-available.
It is LookupVisible except that a library implementing DynamicFunctionLibrary gets to answer for itself; see there for why a host language would scope the two differently.
func LookupVisible ¶ added in v1.1.0
LookupVisible resolves a function the way a call does, hiding one the context's version does not have.
Exported because fn:function-available has to give the same answer a call would: asking the library directly reported every function the engine can implement, so a 2.0 stylesheet was told that map:get and fn:parse-json were available to it and then refused when it called them.
type FunctionCall ¶ added in v1.3.0
FunctionCall is the signature of a function implementation, named so that FunctionSpec and Function refer to one type rather than repeating it.
type FunctionLibrary ¶
type FunctionLibrary interface {
// Lookup returns the function with the given name and arity.
Lookup(name xdm.QName, arity int) (Function, bool)
}
FunctionLibrary resolves and calls functions.
func Builtins ¶
func Builtins() FunctionLibrary
Builtins returns the standard fn: function library.
The library is built once and shared: Function values hold no mutable state (everything they need comes from the Context passed at call time), so a single instance is safe for concurrent transforms. Rebuilding it per transform would cost several hundred map inserts for no benefit.
type FunctionSpec ¶ added in v1.3.0
type FunctionSpec struct {
Name xdm.QName
Arity int
Params []SequenceType
Result SequenceType
// Since is the first language version in which the function exists, with
// the same meaning as Function.Since.
Since Version
// Extension marks an entry that is not an F&O function — a host-language
// addition such as fn:stream-available, which XSLT 3.0 defines for
// streaming and F&O does not define at all. Extensions are excluded from
// F&O completeness counts and are the documented exception to manifest
// coverage.
Extension bool
// Invoke is the implementation, with the signature of Function.Call.
Invoke FunctionCall
}
FunctionSpec is the declared conformance metadata for one (name, arity) entry of the function library.
It is the type the plan names. Invoke sits beside the declared types rather than in a parallel table so that a signature and its implementation cannot drift apart, which is the failure mode a second table would reintroduce.
type IfExpr ¶
type IfExpr struct {
Cond, Then, Else Expr
}
IfExpr is "if (cond) then a else b". Both branches are required by the grammar; there is no one-armed form.
type InlineFunctionExpr ¶ added in v1.1.0
type InlineFunctionExpr struct {
Params []InlineParam
// Result is the declared return type, or nil if none was written.
Result *SequenceType
Body Expr
}
InlineFunctionExpr is "function($x as xs:integer) as xs:integer { $x + 1 }", added in XPath 3.0: a function written where a value is expected.
The body closes over the variables in scope where it is written, which is what makes it more than a named function without a name.
func (*InlineFunctionExpr) Eval ¶ added in v1.1.0
func (e *InlineFunctionExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr: it captures the inline function as a value.
The captured context is what makes this a closure rather than a function definition. "let $n := 2 return function($x) { $x * $n }" returns a function that still knows $n, so the context in scope where the expression was written is the one the body is evaluated in — not the one in scope wherever the function is eventually called.
func (*InlineFunctionExpr) String ¶ added in v1.1.0
func (e *InlineFunctionExpr) String() string
type InlineParam ¶ added in v1.1.0
type InlineParam struct {
Name xdm.QName
// Type is the declared parameter type, or nil if none was written, in
// which case it is item()*.
Type *SequenceType
}
InlineParam is one parameter of an inline function.
type InstanceOfExpr ¶
type InstanceOfExpr struct {
Operand Expr
Type SequenceType
}
InstanceOfExpr is "expr instance of type".
func (*InstanceOfExpr) Eval ¶
func (e *InstanceOfExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr for "instance of".
func (*InstanceOfExpr) String ¶
func (e *InstanceOfExpr) String() string
type KindTest ¶
type KindTest struct {
Kind xdm.NodeKind
// Any matches every kind: the node() test.
Any bool
// Name constrains element()/attribute()/processing-instruction() tests
// that name a target.
Name *xdm.QName
HasName bool
// Content constrains the root element of a document-node() test:
// document-node(element(invoice)) matches only a document whose element
// child satisfies the inner test. Nil means the document's content is
// unconstrained.
Content NodeTest
// TypeName is the second argument of element(name, type) and its
// attribute() counterpart, resolved to the key the data model records
// type annotations under: a namespace-qualified {uri}local for a schema
// type, the bare local name for a built-in. The empty string means the
// test carried no type argument and constrains only the name.
//
// It is resolved at parse time because the prefix binding lives in the
// static context, which is gone by the time the test runs. Comparing the
// lexical form instead forced the comparison down to local parts, and two
// types sharing a local name in different namespaces then matched each
// other.
TypeName string
// TypeNameLexical is TypeName as the author wrote it, kept only so that
// String() renders the test back in the syntax it was parsed from.
TypeNameLexical string
// TypeUnionMembers are the annotation keys of TypeName's member types,
// transitively, when TypeName is a union type.
//
// XPath 3.1 2.5.5 makes union membership a clause of derives-from in its
// own right, and a node validated against a union is annotated with the
// MEMBER that accepted it rather than with the union. So an attribute
// declared as a union of my:partNumberType and xs:integer whose value is
// "44" is annotated "integer", and attribute(*, my:partIntegerUnion)
// matches it only by knowing the members. match-232 asserts exactly that.
//
// The relation runs one way only. These names admit a MEMBER-annotated
// node to the UNION's test; they say nothing about the reverse, and a
// node annotated with the union does not match a test naming one member.
//
// Resolved at parse time, while the schema is still reachable, for the
// same reason SubstitutionGroup is. nil when TypeName is not a union.
TypeUnionMembers []string
// TypeNillable records the "?" of element(name, type?), which lets a
// nilled element match even though its content is absent.
TypeNillable bool
// SchemaDeclared marks a schema-element() or schema-attribute() test,
// which names a global declaration rather than an element name. It
// matches the named declaration and, for an element, the members of its
// substitution group.
SchemaDeclared bool
// SubstitutionGroup holds the other names schema-element(E) admits: the
// members of E's substitution group, resolved from the imported schema
// when the test was parsed.
//
// It is resolved at parse time because nothing carries a schema into the
// evaluator, and the group is fixed once the schema is imported. Nil for
// every test that is not a schema-element(), and for a declaration that
// heads no group.
SubstitutionGroup []xdm.QName
// DeclaredType is the local name of the type the schema-element() or
// schema-attribute() declaration names, resolved at parse time for the
// same reason SubstitutionGroup is. A node whose annotation is neither
// that type nor derived from it was validated against some *other*
// declaration of the same name — a local one — and does not match.
//
// Empty when the declaration's type is anonymous, in which case there is
// no name to compare and the test checks only that the node was
// validated.
DeclaredType string
}
KindTest matches by node kind: text(), comment(), node(), element(name), and so on.
type LetExpr ¶ added in v1.1.0
LetExpr is "let $x := expr return expr", added in XPath 3.0.
It is not a ForExpr with a different keyword. "for" iterates, binding its variable to one item at a time and concatenating the results; "let" binds the whole sequence once and evaluates its body once. "let $x := (1, 2) return count($x)" is 2, where the corresponding "for" is (1, 1).
type Lexer ¶
type Lexer struct {
// contains filtered or unexported fields
}
Lexer turns XPath source into tokens.
XPath 2.0's grammar is not context-free at the lexical level: whether `*` means multiplication or "any element", and whether `div`, `and`, `is` and friends are operators or element names, depends on what preceded them. The spec resolves this with a rule stated in terms of the previous token, and that is what prevOperand tracks. Trying to decide these in the parser instead means the lexer must emit ambiguous tokens and the parser must re-lex, which is worse.
type Library ¶
type Library struct {
// Parent is consulted when a name is not found locally, so a stylesheet's
// own functions can shadow and extend the builtins without copying them.
Parent FunctionLibrary
// contains filtered or unexported fields
}
Library is a mutable function library keyed by expanded name and arity.
Arity is part of the key because XPath overloads on it: fn:string() and fn:string($arg) are different functions, and fn:substring has both a two- and a three-argument form with different behaviour.
func NewLibrary ¶
func NewLibrary(parent FunctionLibrary) *Library
NewLibrary returns an empty library chained to parent.
func (*Library) Declares ¶ added in v1.1.0
Declares reports whether this library itself defines the name, without consulting Parent.
Lookup deliberately chains, so it cannot answer "is this one of the stylesheet's own functions?" for a library whose parent is the builtins. XSLT 3.0 10.4.1 needs exactly that question: the target expression of xsl:evaluate sees the builtin functions but not the ones the stylesheet declares.
type Literal ¶
Literal is a constant atomic value.
type LookupExpr ¶ added in v1.1.0
type LookupExpr struct {
Base Expr
// Name, Index and Wildcard are the three shapes a key specifier takes;
// exactly one is set. Expr is the parenthesised form, "?($k)".
Name string
HasName bool
// Index is the literal position of "?3", held as the atomic the parser
// already built rather than re-encoded as a machine int. An integer
// literal is arbitrary-precision, so "?100000000000000000000000000000000"
// has to survive to evaluation intact and fail there as FOAY0001 with its
// own digits; narrowing it here saturated it to maxint.
Index *xdm.Atomic
HasIndex bool
Wildcard bool
Expr Expr
}
LookupExpr is the postfix lookup operator, "$m?k" and "$a?1", production [54].
UnaryLookup ("?k" with no operand) is the same node with a nil Base, applied to the context item, which is what makes "$maps ! ?name" work.
func (*LookupExpr) Eval ¶ added in v1.1.0
func (e *LookupExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr.
func (*LookupExpr) String ¶ added in v1.1.0
func (e *LookupExpr) String() string
String implements Expr.
type MapConstructor ¶ added in v1.1.0
MapConstructor is "map { k : v, ... }", production [69] of XPath 3.1.
func (*MapConstructor) Eval ¶ added in v1.1.0
func (e *MapConstructor) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr.
func (*MapConstructor) String ¶ added in v1.1.0
func (e *MapConstructor) String() string
String implements Expr.
type NameTest ¶
type NameTest struct {
// Name is the expanded name to match. Wildcards leave one or both parts
// unconstrained; see AnyURI and AnyLocal.
Name xdm.QName
// AnyURI matches any namespace ("*" and "*:local").
AnyURI bool
// AnyLocal matches any local name ("*" and "prefix:*").
AnyLocal bool
}
NameTest matches by expanded name.
type NamedFunctionRef ¶ added in v1.1.0
type NamedFunctionRef struct {
Name xdm.QName
Arity int
// Cast is the cast a reference to the CONSTRUCTOR FUNCTION of an imported
// schema type stands for, with the argument reachable as
// ConstructorArgVar. Nothing registers such a function in the library --
// the set of them is not known until a schema is imported -- so the
// reference is resolved here, while the parser's schema hook is still in
// reach, exactly as foldSchemaConstructor resolves an ordinary call.
// nil for every other reference.
Cast Expr
}
NamedFunctionRef is "fn:concat#3", added in XPath 3.0: a reference to a named function of a given arity, as a value.
The arity is part of the reference because it is part of a function's identity — fn:concat#2 and fn:concat#3 are different functions — and because the name alone would not say which of an overloaded set is meant.
func (*NamedFunctionRef) Eval ¶ added in v1.1.0
func (e *NamedFunctionRef) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr: it resolves the named function and yields it as a value.
Resolution is static in the sense that matters — the name and arity are fixed by the expression — but it happens here rather than at parse time because the function library lives on the context, exactly as it does for an ordinary call.
func (*NamedFunctionRef) String ¶ added in v1.1.0
func (e *NamedFunctionRef) String() string
type NamespaceResolver ¶
type NamespaceResolver interface {
// ResolvePrefix returns the URI bound to prefix, or false if unbound.
ResolvePrefix(prefix string) (string, bool)
// DefaultElementNamespace returns the namespace applied to unprefixed
// element name tests. XSLT sets this from xpath-default-namespace; it is
// empty by default, and it never applies to attribute names or function
// names.
DefaultElementNamespace() string
// DefaultFunctionNamespace returns the namespace for unprefixed function
// names, which is the fn: namespace in XPath and XSLT.
DefaultFunctionNamespace() string
}
NamespaceResolver resolves a namespace prefix to a URI at parse time.
Prefixes must be resolved when the expression is compiled, not when it runs: an XPath expression in a stylesheet is bound to the namespace declarations in scope at the point it appears, and by evaluation time the relevant element is long out of view.
type NodeTest ¶
type NodeTest interface {
// Matches reports whether n is selected on an axis whose principal node
// kind is principal.
Matches(n *xdm.Node, principal xdm.NodeKind) bool
String() string
}
NodeTest decides whether a node on an axis is selected.
type OSEnvironment ¶ added in v1.3.0
type OSEnvironment struct{}
OSEnvironment is an EnvironmentResolver over the real process environment, exposing every variable the process holds.
It is the widest grant this library offers and is never installed by default: a caller who sets it is saying that whatever runs in this context is trusted with the process's own secrets. Prefer a resolver over a fixed map of the variables a stylesheet actually needs.
func (OSEnvironment) EnvironmentNames ¶ added in v1.3.0
func (OSEnvironment) EnvironmentNames() []string
EnvironmentNames returns every variable name in the process environment, sorted. The order is fixed only so that two calls in one query agree; the spec fixes none, and an unstable one would make a test comparing two calls flap.
func (OSEnvironment) LookupEnvironment ¶ added in v1.3.0
func (OSEnvironment) LookupEnvironment(name string) (string, bool)
LookupEnvironment reads the process environment.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser builds an AST from tokens.
type PathExpr ¶
type PathExpr struct {
// Root marks a path that starts at the document root ("/foo" rather
// than "foo").
Root bool
Steps []Expr // Step, or an arbitrary expression in "(...)/foo" form
}
PathExpr is a sequence of steps evaluated left to right, each against the nodes produced by the previous one.
type QuantifiedExpr ¶
QuantifiedExpr is "some $x in seq satisfies test" or the "every" form.
func (*QuantifiedExpr) Eval ¶
func (e *QuantifiedExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr for quantified expressions.
func (*QuantifiedExpr) String ¶
func (e *QuantifiedExpr) String() string
type Regexp ¶ added in v1.0.0
type Regexp interface {
MatchString(s string) bool
FindAllStringSubmatchIndex(s string, n int) [][]int
NumSubexp() int
}
Regexp is what CompileRegexp hands back: the subset of *regexp.Regexp that the XSLT layer uses, so that a pattern needing the backtracking engine can be returned in its place without the caller knowing which it got.
The two implementations differ in one way callers must respect. RE2 cannot fail at match time, so *regexp.Regexp's methods have nowhere to report an error and need none. The backtracking engine *can* fail at match time, by exhausting its step budget, and it reports that through Err() rather than by answering false — answering false would be a guess, and precisely on the inputs where the answer was hardest to get. So a caller that may be holding a backtracking pattern must check Err() after any operation whose result it intends to use. RegexpErr does that check for both implementations.
func CompileRegexp ¶
CompileRegexp exposes the XPath-to-Go regular expression translation for the XSLT layer, which needs it for xsl:analyze-string. The compiled result is cached exactly as it is for fn:matches.
A pattern with a backreference RE2 cannot express is compiled by the backtracking engine instead, but only when that engine is enabled; when it is not, the pattern is refused exactly as before.
func CompileRegexpVersion ¶ added in v1.1.0
CompileRegexpVersion is CompileRegexp for a caller that knows which version of the language the pattern was written in.
CompileRegexp remains the 2.0 spelling so that an existing caller keeps the behaviour it had; a 3.0 host passes XPath30 to admit non-capturing groups, reluctant quantifiers and the "q" flag.
type SchemaImpureUnionTypes ¶ added in v1.3.0
type SchemaImpureUnionTypes interface {
// SchemaUnionAtomicMemberTypes returns the built-in atomic types the named
// union admits directly, transitively through member unions, skipping any
// list member. ok is false when the name is not a union at all.
SchemaUnionAtomicMemberTypes(name xdm.QName) ([]xdm.TypeCode, bool)
}
SchemaImpureUnionTypes reports the ATOMIC member types of a union without requiring the union to be pure.
SchemaUnionMemberTypes refuses an impure union outright, which is right for the ItemType question it answers -- a value must not stand in for a faceted union it may not satisfy. A CAST asks something else: which members a source value may be converted into. F&O defines the cast to a list type from xs:string and xs:untypedAtomic only, so a non-string source may reach a union's atomic members and no others, and that set has to be known even when the union as a whole is impure.
Optional, like the other schema interfaces: a resolver that does not implement it simply reports no atomic members, and every non-string source is refused -- the conservative direction.
type SchemaListTypes ¶ added in v1.1.0
type SchemaListTypes interface {
// SchemaTypeIsList reports whether name is a simple type of variety list,
// and the name of its item type when it is.
SchemaTypeIsList(name xdm.QName) (itemType xdm.QName, ok bool)
}
SchemaListTypes reports whether a named simple type is of variety list.
It is separate from SchemaTypes for the same reason SchemaUnionTypes is: optional, so an implementation that does not know about list types simply does not implement it and nothing changes.
A list type is a legal cast target -- F&O 3.0 18.3 covers "casting to types derived by restriction, to union types, and to list types" -- but its value is a whitespace-separated SEQUENCE rather than one atomic item, so it can never satisfy the "cast target must be an atomic type" rule that guards the ordinary path. Recognising it needs the schema: the built-in list types are known by name, but a schema-defined one is not.
type SchemaTypes ¶ added in v1.0.0
type SchemaTypes interface {
// LookupSchemaType reports whether name is a type in the static context,
// and which primitive an atomic value of it erases to.
//
// The primitive is what the type *system* needs: "instance of" and "treat
// as" compare against the type hierarchy, and a value of a derived atomic
// type is a value of its primitive with facets applied. A complex type,
// or a list or union with no single primitive, returns ok with a zero
// code and false for atomic — enough to stop XPST0051 without claiming
// the value is comparable as an atomic.
LookupSchemaType(name xdm.QName) (prim xdm.TypeCode, atomic, ok bool)
// LookupSchemaDeclaration reports whether name is a global element or
// attribute declaration in the static context.
//
// It is what schema-element() and schema-attribute() need: both name a
// *declaration* rather than a type, and both are XPST0008 when no schema
// declares the name.
LookupSchemaDeclaration(name xdm.QName, attribute bool) bool
// SubstitutionGroupMembers returns the global element declarations that
// may substitute for name, transitively and not including name itself.
//
// schema-element(E) matches E and every member of E's substitution
// group, so a schema that declares "surname" as substitutable for "last"
// makes schema-element(z:last) match a z:surname element. Resolving the
// members here rather than at match time is what keeps the node test
// self-contained: nothing carries a schema into the evaluator, and the
// group is fixed once the schema is imported.
//
// An implementation with no schema, or a name with no members, returns
// nil.
SubstitutionGroupMembers(name xdm.QName) []xdm.QName
// SchemaDeclarationType returns the local name of the type a global
// element or attribute declaration names, and whether there is one.
//
// It is a LOCAL name, unlike the type name in an element() test, which is
// resolved to a namespace-qualified annotation key at parse time. The
// difference is deliberate: this string is produced by an implementation
// of this interface, which has no obligation to know about annotation
// keys, so the comparison against it (in nodeTypeMatches, reached through
// KindTest.DeclaredType) accepts a bare name as a local-part match. That
// is narrower ground than it sounds: the check exists only to tell a
// global declaration from a LOCAL declaration of the same name in the
// same schema, where the namespace is not in question.
//
// schema-element(E) matches a node only when it was validated against
// E's *declaration*, and a node may carry E's name while having been
// validated against a local declaration of a different type — which is
// the case the suite draws the line on. The evaluator sees only the
// compiled test, so the declared type is resolved here, while the schema
// is still reachable, and compared against the node's annotation at
// match time.
//
// An anonymous type has no name to return, so a declaration using one
// returns false and the test falls back to checking only that the node
// was validated at all.
SchemaDeclarationType(name xdm.QName, attribute bool) (string, bool)
// ValidateSchemaValue checks a lexical value against a named simple type
// in the static context, reporting whether the name is a simple type at
// all and, if so, whether the value is in its value space.
//
// "castable as my:hatsize" is that question. The engine can cast to the
// built-in the type derives from, but the facets the schema author wrote
// live only in the schema — so without asking, a cast to a restriction of
// xs:integer accepted every integer and the restriction meant nothing.
ValidateSchemaValue(name xdm.QName, value string) (known bool, err error)
}
SchemaTypes reports the types an imported schema contributes to the static context.
XPath 2.0 has an *in-scope schema definitions* component that this engine otherwise leaves empty: without it, only the built-in xs: types exist, and "instance of my:partNumberType" is XPST0051 no matter what the stylesheet imported. A stylesheet with xsl:import-schema is precisely the case where that component is not empty.
It is an interface here rather than an *xsd.Schema because xsd imports xpath — schema documents contain XPath expressions in their assertions and selectors — so the dependency cannot run the other way. The xslt package supplies the implementation, which is a few lines over the schema's own type table.
A resolver that also implements this is asked about a name only after the built-in table has declined it, so a schema cannot redefine xs:integer.
type SchemaUnionListMembers ¶ added in v1.3.0
type SchemaUnionListMembers interface {
// SchemaUnionListMemberNames returns the names of the named union's list
// members, in declaration order and transitively through member unions.
// ok is false when the name is not a union at all.
SchemaUnionListMemberNames(name xdm.QName) ([]xdm.QName, bool)
}
SchemaUnionListMembers reports the LIST members of a union, by name.
It is the other half of the question SchemaUnionAtomicMemberTypes answers. A cast to a list type produces a SEQUENCE -- F&O 3.0 18.3.6 makes the effect "the same as ... validating it using L as the governing type, and atomizing the resulting node", and its own example has my:coordinates("2 -1") return two xs:integer values. So when a string-like source is admitted by a union's list member, the result is that list's items and not the one string that was handed in, and the list has to be known to build them.
The count is what the suite pins. cbcl-castable-impure-010 asks for "s:impureUnionType('1 2 3') castable as s:impureUnionType" to be FALSE: the inner constructor yields THREE xs:decimal values, and a three-item sequence is not castable to anything. Returning the single string made it true.
The members are reported by NAME rather than as one item code, because the code lost what the cast owes. A union over xs:IDREFS and a list of a union (CastAs-UnionType-27 and -28) yields xs:IDREF values from the one member and union-member values from the other, and xs:IDREFS is a built-in the schema's own type table does not hold -- so asking it for the item type answered nothing, and the single string came back. The name is resolved on the xpath side into a full cast target, the same way a list's item type is.
Optional in the same way as the interfaces above: a resolver that does not implement it reports no list member, and the result keeps its old shape.
type SchemaUnionMemberFacets ¶ added in v1.3.0
type SchemaUnionMemberFacets interface {
// SchemaUnionMemberFacetNames returns one name per entry of
// SchemaUnionMemberTypes: a built-in member's bare local name
// ("NCName"), and the empty string for a member with no built-in name to
// apply. ok is false when the name is not a pure union.
SchemaUnionMemberFacetNames(name xdm.QName) ([]string, bool)
// SchemaUnionAtomicMemberFacetNames is the same, one name per entry of
// SchemaUnionAtomicMemberTypes: an IMPURE union's atomic members, which a
// cast reaches by the same rule and which lose the same information.
// CastAs-UnionType-34 casts to a pattern-restricted union over xs:date and
// three Gregorian types and requires an xs:date back.
SchemaUnionAtomicMemberFacetNames(name xdm.QName) ([]string, bool)
}
SchemaUnionMemberFacets reports the NAMES of a union's member types, in the same order and with the same membership as the codes reported alongside.
It exists because those codes are lossy in exactly the way a CAST cares about. XPath erases every derived string type to xs:string, so a union over xs:NCName and xs:QName reports two codes, xs:string and xs:QName, and casting to the first produced a bare xs:string. F&O 3.0 18.3.2 makes the result of a cast to a union an instance of the MEMBER that accepted it, so "s:sensitiveUnion('candlewick') instance of xs:NCName" must be true -- CastAs-UnionType-18 asserts it, and the erased code cannot carry the fact. The name can: CastToDerived applies the facet the code cannot express and annotates the result with it.
It is separate from SchemaUnionNames, which reports the annotation keys a validated NODE may carry: that walk is deliberately looser about purity and deliberately non-parallel (it skips members already seen), so its slice cannot be indexed alongside the codes.
Optional in the same way as every other schema interface here: a resolver that does not implement it reports no names, and a cast to a union keeps the erased member code it always had.
type SchemaUnionNames ¶ added in v1.1.0
SchemaUnionMemberNames reports the annotation keys of a union type's member types, transitively.
It is separate from SchemaUnionMemberTypes because it answers a different question for a different consumer. That method erases each member to the built-in atomic type code an unannotated VALUE would carry, which is what "instance of" compares against. A NODE carries the name it was validated against instead, so an attribute validated as a union's xs:integer member is annotated "integer" and matching it against the union needs the names.
It is also deliberately looser about purity: a union used here need not be pure. Purity exists to stop a member VALUE from standing in for a faceted union it may not satisfy — the XSD 1.0 error XSD 1.1 3.16.6.3 corrected — but a node reaching this point was actually validated against the union, so the schema has already decided it satisfies whatever facets the union adds. The unsafe substitution purity guards against cannot arise.
It is STRICTER in the one way that matters instead: only atomic members are reported. A union over list types annotates the node with the union itself rather than with a member, so naming its members would admit no node that should match and would admit sibling members that should not.
type SchemaUnionTypes ¶ added in v1.1.0
type SchemaUnionTypes interface {
// SchemaUnionMemberTypes returns the built-in atomic types a pure union
// type admits, transitively, and whether name is a pure union type at
// all.
//
// "Pure" is XPath 3.1 2.5's term and its constraints are the caller's to
// enforce: variety union, no facets, no list type in the transitive
// membership, and no member union carrying facets. A union failing any of
// them returns false — XSD 1.1 fixed a 1.0 error here, and matching such
// a type is unsafe rather than merely unsupported.
SchemaUnionMemberTypes(name xdm.QName) ([]xdm.TypeCode, bool)
}
SchemaUnionTypes reports the member types of a pure union type.
It is separate from SchemaTypes rather than a method on it because it is optional: an implementation that does not know about unions simply does not implement it, and every union then matches nothing, which is the behaviour before this existed. Folding it into SchemaTypes would have broken every implementation of that interface instead.
type ScopedFunctionLibrary ¶ added in v1.2.1
type ScopedFunctionLibrary interface {
FunctionLibrary
// LookupFrom returns the function a call written in ctx's package resolves
// to, or false where that package may not see it.
LookupFrom(ctx *Context, name xdm.QName, arity int) (Function, bool)
}
ScopedFunctionLibrary is a FunctionLibrary whose answer to an ORDINARY call depends on where the call is written.
Plain XPath has no such notion: a function is either in the static context or it is not, and one library answers for the whole expression. XSLT 3.0 packages break that. 3.6.3.4 puts in a package's static context only "the components of the packages it uses that are visible to it" -- public, final or abstract -- so a PRIVATE function of a used package is not callable from the using package even though it is perfectly callable from inside the package that declares it. One name, two answers, decided by the caller.
The context is passed for the same reason DynamicFunctionLibrary passes it: the package a call was written in is a property of the expression, carried on Context.StaticHost.
A library that does not implement this is scoped the same wherever it is called from, which is what XPath on its own means.
type SequenceExpr ¶
type SequenceExpr struct{ Items []Expr }
SequenceExpr is a comma-separated sequence constructor.
func (*SequenceExpr) Eval ¶
func (e *SequenceExpr) Eval(ctx *Context) (xdm.Sequence, error)
Eval implements Expr for a sequence constructor.
func (*SequenceExpr) String ¶
func (e *SequenceExpr) String() string
type SequenceType ¶
type SequenceType struct {
// Empty is the empty-sequence() type.
Empty bool
// ItemType is nil for item(), which matches anything.
ItemType NodeTest
// AtomicType names an atomic type when the item type is one.
AtomicType xdm.TypeCode
HasAtomicType bool
// IsFunctionTest marks a function(*) or function(...) as ... item type,
// which matches a function item. A typed test additionally fixes the
// arity and, where the function item records a signature of its own, the
// parameter and return types it must be compatible with.
IsFunctionTest bool
FunctionArity int
HasFunctionArity bool
// FunctionParams and FunctionReturn are the typed test's declared
// parameter and return types. They are matched only against a function
// item that records its own signature; one that does not is judged on
// arity alone. Every standard function now carries its manifest
// signature, so that path is reached only by a function with no declared
// type to read -- an untyped inline function, or a host extension.
FunctionParams []SequenceType
FunctionReturn *SequenceType
// IsArrayTest marks an "array(*)" or "array(T)" item type, added in 3.1.
//
// An array is also a function item, so a function test can match one too;
// the reverse does not hold, which is why this is a flag of its own rather
// than a shape of IsFunctionTest. ArrayMember is the declared member type
// of "array(T)", against which *every* member sequence is checked —
// members are sequences, so "array(xs:string)" admits only arrays whose
// members are each exactly one string.
IsArrayTest bool
ArrayMember *SequenceType
// IsMapTest marks a "map(*)" or "map(K, V)" item type, added in 3.1, on
// the same reasoning as IsArrayTest: a map is also a function item, so a
// function test matches one, but a map test matches only a map.
//
// MapKey is the declared key type, an atomic type with no occurrence
// indicator, and MapValue the declared value type, checked against every
// entry's value sequence.
IsMapTest bool
MapKey *SequenceType
MapValue *SequenceType
// IsErrorType marks xs:error, the empty type. Nothing is an instance of
// it, so it matches only the empty sequence — and only then because the
// occurrence indicator permits it, never because an item conformed.
IsErrorType bool
// IsNumericType marks xs:numeric, the union of xs:double, xs:float and
// xs:decimal that XPath 3.1 adds.
//
// It is a union rather than an atomic type, so it has no TypeCode of its
// own: an item is an instance of it when its type is any of the three or
// derived from one, which is what makes xs:short an xs:numeric. A cast to
// it is the identity on a value that already is one and a cast to
// xs:double on anything else, so the written name has to survive to the
// cast rather than collapsing to a type code here.
IsNumericType bool
// ListItemFacet is the item type's facet name when the written type is
// one of the built-in list types -- "NMTOKEN" for xs:NMTOKENS. A list
// type's value is a sequence, so no TypeCode stands for it and the name
// has to survive to the cast; see listtype.go.
ListItemFacet string
// FacetName is the derived type actually written, when it differs from
// AtomicType — "byte" for xs:byte, which is an xs:integer with a range.
// The code alone cannot express the bound, and dropping it made
// "128 castable as xs:byte" answer true.
FacetName string
// SchemaType is the lexical name of a type that came from an imported
// schema rather than from the built-in table.
//
// It is kept as written because that is what the schema's own type table
// is keyed by: matching a value against it means asking the schema, not
// the type codes here, and a derived type's identity is exactly its name.
SchemaType string
// SchemaValueValid checks a lexical value against the imported schema
// type SchemaType names, when that name is a simple type. It is captured
// at parse time, while the schema is still reachable through the
// resolver, for the same reason a schema-element() test's substitution
// group is: nothing carries a schema into the evaluator.
//
// nil when the type is not an imported simple type, in which case a cast
// is decided entirely by the built-in the type derives from.
SchemaValueValid func(value string) error
// SchemaExpandQName resolves a lexical QName against the namespace
// bindings in scope where the type name was written, when the type's
// value space is the QName one.
//
// A cast to xs:QName or to a type derived from xs:NOTATION cannot be
// completed without it: the namespace comes from the static context, and
// by evaluation time that context is gone -- CastToDerived produces a
// QName with no URI, which is why the parser folds the literal case. A
// computed operand has no literal to fold, so the bindings are captured
// here instead, alongside SchemaValueValid and for the same reason.
//
// nil unless the type is QName-valued.
SchemaExpandQName func(lexical string) (xdm.QName, bool)
// SchemaUnionMembers are the built-in atomic types a *pure union type*
// from an imported schema admits, transitively.
//
// XPath 3.1 2.5.5 writes union membership as its own clause of
// derives-from — "ET is a pure union type of which AT is a member type" —
// so a value is an instance of the union whenever its actual type is one
// of the members. No validation and no annotation are involved: the
// xs:date that fn:current-date returns is an instance of a union over
// xs:date, xs:time and xs:dateTime purely because xs:date is a member.
//
// Resolved at parse time, while the schema is still reachable, for the
// same reason SchemaValueValid is. nil for anything that is not a pure
// union, which is what keeps the impure cases 2.5 excludes — a union
// carrying facets, or one with a list type anywhere in its transitive
// membership — matching nothing rather than matching too much.
SchemaUnionMembers []xdm.TypeCode
// SchemaUnionMemberFacets are the member type NAMES of the same union, one
// per entry of SchemaUnionMembers and in the same order, or nil when the
// resolver cannot supply them.
//
// A CAST to a union produces an instance of the member that accepted the
// value, and the erased code cannot say which derived type that was: a
// union over xs:NCName and xs:QName reports xs:string for the first, so
// the cast returned a bare string and "instance of xs:NCName" was false.
// The name is what CastToDerived needs to apply the facet and annotate the
// result. See SchemaUnionMemberFacets.
SchemaUnionMemberFacets []string
// SchemaListType marks a schema-defined simple type of variety list
// written in type position.
//
// It is the schema-defined counterpart of ListItemFacet, which covers
// only the three built-in list types the engine knows by name. Both say
// the same thing -- the value is a sequence of whitespace-separated
// tokens, not one atomic item -- and both exist so that a cast to such a
// type is not rejected by the atomic-target rule. The difference is how
// the tokens are checked: a built-in list applies a known item facet,
// while a schema-defined one is validated in full by the schema through
// SchemaValueValid, which already applies the item type AND the list's
// own facets.
SchemaListType bool
// SchemaListItemType is the built-in atomic type each whitespace-
// separated token of a SchemaListType value is cast to, or the zero code
// when the item type is itself schema-defined and has no built-in code.
// Castability does not depend on it -- the schema decides that through
// SchemaValueValid -- but the cast's result sequence does.
SchemaListItemType xdm.TypeCode
// SchemaListItem is the item type of the same list, resolved as a cast
// target in its own right, or nil when the resolver cannot supply it.
//
// SchemaListItemType is lossy in the way a cast cares about. XPath erases
// every derived string type to xs:string, so a list of xs:IDREF built
// three bare strings where F&O 3.0 18.3.6 owes three values "each of
// which is an instance of the item type"; and a list whose item type is
// a union has no code at all, so its tokens stayed the strings they were
// handed in as. CastAs-UnionType-27 asks for xs:IDREF* and
// CastAs-ListType-21 for an xs:NCName that is also an instance of the
// union. Each token is cast to THIS type, through the same rules as a
// cast written against it, so the facet is applied, the member chosen and
// the annotation recorded. The code stays as the fallback for a resolver
// that answers only the older question.
SchemaListItem *SequenceType
// SchemaSimpleType marks a named schema simple type that is a legal cast
// target but has no shape any of the fields above can describe: an
// *impure* union -- one carrying facets, or one holding a list type
// anywhere in its transitive membership -- and a union derived by
// restriction.
//
// The distinction from SchemaUnionMembers is which question is being
// asked, not which types exist. XPath 3.1 2.5 admits only a *pure* union
// as an ItemType, because "instance of" has to answer from a value's own
// annotation and a faceted union's members do not necessarily satisfy its
// facets -- the XSD 1.0 error 1.1 3.16.6.3 corrected. But 3.14.2 admits
// any simple type in the in-scope schema types as a cast target, and a
// cast has a lexical form in hand to validate, so the objection does not
// arise: castability is the schema's own ValidateValue answer.
// cbcl-castable-impure-001 asserts that
// "xs:date('2001-01-01') castable as s:impureUnionType" is true, not an
// error, and the purity rule still governs every ItemType position.
//
// SchemaValueValid is what decides a value; this field only says that the
// name denotes such a type, so the atomic-target rule lets it through.
SchemaSimpleType bool
// SchemaSimpleListMembers are the LIST members of the impure union
// SchemaSimpleType marks, in declaration order, each resolved as a cast
// target of its own: SchemaListType set, SchemaListItem carrying the item
// type, SchemaValueValid the member's own validity.
//
// A cast to a list type produces a SEQUENCE, one value per whitespace-
// separated token (F&O 3.0 18.3.6). A union holding a list member is
// impure, so such a cast arrives here rather than in the list-type branch
// above, and without this the result was the single string handed in.
// cbcl-castable-impure-010 is what that cost: the constructor
// "s:impureUnionType('1 2 3')" owes three xs:decimal values, and a
// three-item sequence is not castable to anything -- so the outer
// "castable as s:impureUnionType" is false, where one string made it true.
//
// The members are whole types rather than one item code because the code
// could not say which list admitted the value, nor what its items are
// beyond a built-in primitive. A union over xs:IDREFS and a list of a
// union (CastAs-UnionType-27 and -28) owes xs:IDREF values from the first
// and union-member values from the second, and which one applies is
// decided by trying them in order -- the rule for every union.
//
// Only a string-like source reaches a list member at all; an atomic
// source is confined to SchemaSimpleAtomicMembers, which is the rule that
// separates -005 from -009. nil when the union has no list member.
SchemaSimpleListMembers []SequenceType
// SchemaSimpleAtomicMembers are the built-in atomic types an impure union
// admits directly, ignoring any list member.
//
// It is what separates cbcl-castable-impure-001 from -009. impureUnionType
// is a union of xs:date and a list of xs:decimal, and the suite asks for
// true from an xs:date and FALSE from an xs:decimal -- even though "1" is
// a perfectly good one-item list of decimals. The difference is the SOURCE
// type: F&O defines a cast to a list type from xs:string and
// xs:untypedAtomic only, so a non-string source can reach a union's ATOMIC
// members and nothing else. A string-like source may reach every member,
// which is why "1 2 3" as an xs:untypedAtomic is castable (-005) and the
// same value already typed as the union is not (-010).
//
// nil when the type has no atomic member, which refuses every non-string
// source -- the right answer for a union over list types alone.
SchemaSimpleAtomicMembers []xdm.TypeCode
// SchemaSimpleAtomicFacets are those members' NAMES, one per entry and in
// the same order, or nil when the resolver cannot supply them. It is
// SchemaUnionMemberFacets for the impure case, and exists for the same
// reason: the cast's result is an instance of the member that accepted the
// value, and the erased code cannot say which derived type that was.
SchemaSimpleAtomicFacets []string
// Occurrence is "", "?", "*" or "+".
Occurrence string
}
SequenceType is a type annotation: an item type plus an occurrence indicator.
func ParseSequenceType ¶ added in v1.2.0
func ParseSequenceType(src string, ns NamespaceResolver) (SequenceType, error)
func (SequenceType) AllowsEmpty ¶ added in v1.3.0
func (t SequenceType) AllowsEmpty() bool
AllowsEmpty reports whether the declared type permits an empty sequence: true for "?" and "*", false for "" and "+".
This one question is the whole of the twelve-function defect class. F&O 3.1 2.5.4 makes passing () to a parameter whose declared type carries no "?" or "*" a type error; twelve functions instead treated it as a default value, an empty result, or a silent zero.
empty-sequence() is the type of which () is the only instance, so it permits an empty sequence whatever indicator it carries.
func (SequenceType) AllowsMany ¶ added in v1.3.0
func (t SequenceType) AllowsMany() bool
AllowsMany reports whether the declared type permits more than one item.
func (SequenceType) Matches ¶
func (t SequenceType) Matches(seq xdm.Sequence) bool
Matches reports whether seq conforms to the sequence type.
func (SequenceType) MatchesItem ¶ added in v1.0.0
func (t SequenceType) MatchesItem(it xdm.Item) bool
MatchesItem reports whether a single item conforms to the sequence type's item type, ignoring the occurrence indicator.
The function conversion rules need this separately from Matches: subtype substitution says an item that already conforms is passed through untouched, and only an item that does not conform is a candidate for atomisation, casting or promotion.
func (SequenceType) String ¶
func (t SequenceType) String() string
type SerializeParams ¶ added in v1.1.0
type SerializeParams struct {
// AllowDuplicateNames permits a JSON object to be written with two keys
// that render to the same string; without it that is SERE0022.
AllowDuplicateNames bool
// Indent asks for whitespace around the JSON structural tokens.
//
// Serialization 3.1 section 9.1.4 makes this the one parameter of the two
// that is optional in a direction: for indent=yes the serializer MAY add
// whitespace, and for indent=no it MUST NOT. So compact output was always
// conformant, and remains exactly what is written when this is false.
Indent bool
// JSONNodeOutputMethod is the method a node nested inside a JSON value is
// serialised with, since JSON itself has no node type. Empty means the
// default, "xml".
JSONNodeOutputMethod string
// ItemSeparator, when HasItemSeparator is set, goes between the items of
// an adaptive result in place of the newline the method otherwise writes.
ItemSeparator string
HasItemSeparator bool
// CharMap maps a character to the string that replaces it on output, as
// xsl:character-map defines.
CharMap map[rune]string
// Normalize applies the requested Unicode normalization form, or is nil
// when the normalization-form parameter was "none". The caller supplies
// the function rather than the form's name because normalisation cannot
// be left until the document is finished: a character map's replacement
// is exempt from it, so the two have to be interleaved here, where the
// map is applied.
Normalize func(string) string
// Encoding is the output encoding. Nothing is transcoded -- both methods
// return a string -- but the JSON method escapes a character the named
// encoding could not have held, and only the caller knows which was
// asked for.
Encoding string
// Budget is the evaluation whose MaxBytes allowance the serialized bytes
// are charged against. These two entry points are a host boundary --
// xslt's own serializer reaches the JSON and adaptive methods through
// them, carrying no Context of its own -- so without it the bytes a
// transform serializes are the one string production nothing charges.
//
// Nil is unbounded, which is what a caller who does not set it gets and
// what both functions did before the field existed.
Budget *Context
}
SerializeParams are the serialization parameters a caller outside this package can set for SerializeJSON and SerializeAdaptive.
It is deliberately narrow. The full serializeOptions set is what fn:serialize reads out of its own parameter argument, and most of it — the XML declaration, CDATA sections, indentation — has no meaning under either of these two methods. What a caller does need is the handful the JSON and adaptive rules actually consult, so that xsl:result-document/@method="json" behaves as fn:serialize with the same parameters would.
type SimpleMap ¶ added in v1.0.0
SimpleMap is the XPath 3.0 "!" operator: the right operand is evaluated once per item of the left, with that item as the context item, and the results are concatenated.
Unlike "/" it neither requires nodes nor sorts, which is the whole reason the suite's assertions use it — "string-to-codepoints(...)!string()" maps over integers, where "/" would raise XPTY0019.
type StaticCall ¶ added in v1.1.0
type StaticCall struct {
Name xdm.QName
Arity int
// Ref marks a "name#arity" reference rather than a call. The two differ
// in what a missing function means to the host language, so the caller is
// told which it found.
Ref bool
// StringArgs holds the arguments of a call that are string literals, one
// entry per argument position, nil wherever the argument is anything
// else. It is empty for a Ref, which has no arguments.
//
// A host language whose error is about the *value* of a literal argument
// can decide it without waiting for the call to be reached: XSLT's
// XTDE3490 asks whether the name written in current-merge-group('x')
// is one of the merge sources, and says the error "may be reported
// statically if it can be detected statically". Only literals are
// reported, because an argument that has to be evaluated has no static
// value -- which is the same line checkMergeKeyCompatibility draws.
StringArgs []*string
}
StaticCall is one function call or named function reference written in an expression, reported by Compiled.StaticCalls.
type Step ¶
type Step struct {
Axis Axis
Test NodeTest
Predicates []Expr
// Explicit records that the axis was written out ("child::x") rather
// than abbreviated ("x"). Section 5.5.3 gives the abbreviated child axis
// in a pattern a wider reach than the written one — it is evaluated on
// the child-or-top axis, so "document-node()" alone matches the document
// node while "child::document-node()" is legal but matches nothing,
// since a document node is never a child.
Explicit bool
}
Step is one step of a path: an axis, a node test, and zero or more predicates.
func (*Step) Eval ¶
Eval implements Expr for a single axis step.
A step is evaluated against the context item alone; iterating a step over many context nodes is PathExpr's job. Splitting it this way means the predicate's context size is the number of nodes selected by *this* step from *this* node, which is what the spec requires and what a combined implementation typically gets wrong.
type StringConcat ¶ added in v1.0.0
StringConcat is the XPath 3.0 "||" operator.
It is defined as fn:concat($a, $b), which means it atomizes each operand, requires at most one item from each, and treats the empty sequence as the zero-length string rather than propagating it — so "() || 'x'" is "x" and not the empty sequence.
func (*StringConcat) Eval ¶ added in v1.0.0
func (e *StringConcat) Eval(ctx *Context) (xdm.Sequence, error)
func (*StringConcat) String ¶ added in v1.0.0
func (e *StringConcat) String() string
type TextResolver ¶ added in v1.0.0
type TextResolver interface {
// ResolveText returns the text of uri, resolved against base, decoded
// using encoding when one is named and as UTF-8 when it is empty.
ResolveText(uri, base, encoding string) (string, error)
}
TextResolver reads a resource as text for fn:unparsed-text.
It is deliberately separate from DocumentResolver rather than reusing it. fn:doc parses what it reads as XML, so a resolver granting it hands out well-formed documents; fn:unparsed-text hands the stylesheet the raw bytes of any file the resolver will open, which is a strictly larger disclosure and a different decision for the caller to make. Nil disables the function, which is the default and the safe one.
type Token ¶
type Token struct {
Kind TokenKind
Val string
Pos int
// Num holds the parsed numeric value and NumType its XPath type, so the
// parser does not re-parse the literal. A numeric literal's type is fixed
// by its lexical form: no dot or E means integer, a dot means decimal, an
// E means double.
Num float64
// contains filtered or unexported fields
}
Token is a lexical token with its source offset, which error messages use to point at the offending construct.
type TreatExpr ¶
type TreatExpr struct {
Operand Expr
Type SequenceType
}
TreatExpr is "expr treat as type": a static assertion that does not convert.
type TreeValidator ¶ added in v1.1.0
type TreeValidator interface {
// ValidateJSONTree assesses a document node holding the XML
// representation of JSON against the schema of F&O 3.1 §C.2, annotating
// the tree in place.
//
// The tree was constructed by this package a moment ago and is reachable
// from nowhere else, so mutating it is safe in a way that annotating a
// source document would not be.
//
// An implementation that has the schema but finds the tree invalid
// returns the error. That should not happen for a tree fn:json-to-xml
// built — the construction rules of §17.4.2 produce a valid instance by
// construction, and duplicates="retain", the one option that does not,
// is already refused alongside validate=true — but a wrong answer is
// worth a diagnosis rather than a silently untyped tree.
ValidateJSONTree(doc *xdm.Node) error
}
TreeValidator validates a tree this package has just constructed, writing the type annotations the assessment produces onto its nodes.
fn:json-to-xml is the one function in the library that must do this. F&O 3.1 §17.5.3 says of its validate option: true "indicates that the resulting XDM instance must be typed; that is, the element and attribute nodes must carry the type annotations that result from validation against the schema given at C.2 Schema for the result of fn:json-to-xml".
It is an interface here rather than an *xsd.Schema for the same reason SchemaTypes is: xsd imports xpath, because schema documents contain XPath expressions in their assertions and selectors, so the dependency cannot run the other way. The xslt package supplies the implementation over the schema its xsl:import-schema declarations assembled.
SchemaTypes is the sibling of this and answers a different question: it is consulted while an expression is being *parsed*, about names the static context knows, and it reaches this package as a property of the namespace resolver. This one is consulted while an expression is being *evaluated*, about a tree that exists, so it is a property of the dynamic context.
A nil TreeValidator means the processor cannot validate. That is not a silent no-op: F&O 3.1 §17.5.3 raises FOJS0004 "if the value of the validate option is true and the processor does not support schema validation or typed data", so the caller reports it rather than returning an untyped tree that would fail every assertion the stylesheet then makes about it.
type UnaryOp ¶
UnaryOp is prefix + or -.
type VarQualifier ¶ added in v1.1.0
QualifyVar, when set, is consulted before a variable reference is resolved by name, and answers the name the reference should actually bind to.
It exists for a host language whose variable scopes are not flat. XSLT 3.0 packages are the case: two packages may each declare a global of the same name, and both bindings are live at once, so the name alone does not identify the variable. The host attaches the package to the expression via WithStaticHost and reads it back here. Returning the name unchanged, or leaving the field nil, is the ordinary flat behaviour.
type VarRef ¶
VarRef is a variable reference, $name.
type Version ¶ added in v1.1.0
type Version int
Version selects the version of the XPath language an expression is written in.
The two versions are not a superset relationship in every detail. XPath 3.0 adds constructs — non-capturing groups and reluctant quantifiers in regular expressions, the "q" flag, "let", function items — but a 2.0 processor is required to *reject* those, not to accept them quietly. A stylesheet that relies on one and is run as 2.0 must fail here exactly as it would on any other conforming processor, rather than working here and failing there.
The zero value is XPath20, so every existing caller keeps the behaviour it had before this type existed. Parse compiles 2.0; ParseVersion opts in.
const ( // XPath20 is XPath 2.0, as defined by the 2010 Recommendation. XPath20 Version = iota // XPath30 is XPath 3.0, as defined by the 2014 Recommendation. It admits // everything in 2.0 with the same meaning, plus the 3.0 additions. XPath30 // XPath31 is XPath 3.1, as defined by the 2017 Recommendation. Its // additions are maps and arrays — two new kinds of item rather than new // syntax over the existing ones — together with the lookup operator that // reaches into them and the function libraries that build them. XPath31 )
func (Version) AtLeast30 ¶ added in v1.1.0
AtLeast30 and AtLeast31 are the exported spellings of atLeast30 and atLeast31, for a host that has to make the same distinction the engine does — the XSLT layer decides whether a stylesheet gets the predeclared map: and array: prefixes on exactly this question.
Source Files
¶
- argcardinality.go
- ast.go
- ast_string.go
- axes.go
- builtins.go
- cache.go
- cast.go
- classdiff.go
- coerce_export.go
- collation.go
- compat.go
- context.go
- eval.go
- fn_31.go
- fn_analyze.go
- fn_array.go
- fn_date.go
- fn_document.go
- fn_formatinteger.go
- fn_hof.go
- fn_json.go
- fn_map.go
- fn_math.go
- fn_misc.go
- fn_misc30.go
- fn_node.go
- fn_path.go
- fn_qname.go
- fn_regex.go
- fn_seq.go
- fn_seq30.go
- fn_serialize.go
- fn_stream.go
- fn_string.go
- formatnumber.go
- funcitem.go
- funcspec.go
- funcspec_table.go
- functions.go
- host.go
- lexer.go
- listtype.go
- maparray.go
- mapfuncitem.go
- nsaxis.go
- operators.go
- optimize.go
- order_export.go
- parser.go
- parser_path.go
- qnamedyn.go
- rangeprops.go
- refversion.go
- regex_backref.go
- regex_backtrack.go
- regex_grammar.go
- schema_anchors.go
- schema_grammar.go
- schema_types.go
- staticcalls.go
- staticvars.go
- subtype.go
- treevalidator.go
- typeexpr.go
- version.go
- xpath.go