Implicit class extending QNames with easy conversions to ENames, using this Scope.
Alias for append
Alias for minus
Alias for append(Scope.from((prefix, namespace)))
Returns Scope(this.prefixNamespaceMap ++ scope.prefixNamespaceMap)
Returns the default namespace, if any, wrapped in an Option
Returns Scope.from(this.prefixNamespaceMap.filter(p)).
Returns Scope.from(this.prefixNamespaceMap.filterKeys(p)).
Returns filter(kv => p(kv._2)).
Convenience method, returning the equivalent of:
Convenience method, returning the equivalent of:
this.resolve(
Declarations.from(prefixForNamespace(namespaceUri, getFallbackPrefix) -> namespaceUri))If the namespace is "http://www.w3.org/XML/1998/namespace", this Scope is returned.
If the fallback prefix is used and conflicts with an already used prefix (including ""), an exception is thrown,
as documented for method prefixForNamespace.
The following property holds:
this.subScopeOf(this.includingNamespace(namespaceUri, getFallbackPrefix))
Returns the inverse of this Scope, as Map from namespace URIs to collections of prefixes.
Returns the inverse of this Scope, as Map from namespace URIs to collections of prefixes. These prefixes also include the empty String if this Scope has a default namespace.
Returns true if this Scope is empty.
Returns true if this Scope is empty. Faster than comparing this Scope against the empty Scope.
Returns true if the inverse exists, that is, each namespace URI has a unique prefix (including the empty prefix for the default namespace, if applicable).
Returns true if the inverse exists, that is, each namespace URI has a unique prefix (including the empty prefix for the default namespace, if applicable).
In other words, returns true if the inverse of toMap is also a mathematical function, mapping namespace URIs to unique prefixes.
Invertible scopes offer a one-to-one correspondence between QNames and ENames. This is needed, for example, for Paths.
Only if there is such a one-to-one correspondence, the indexes in Paths and PathBuilders are stable, when converting
between the two.
Returns this.prefixNamespaceMap.keySet.
Returns an invertible Scope having the same namespaces but only one prefix per namespace.
Returns an invertible Scope having the same namespaces but only one prefix per namespace. If this Scope has a default namespace, the returned Scope possibly has that default namespace as well.
Returns the smallest sub-declarations decl of declarations such that this.resolve(decl) == this.resolve(declarations)
Returns Scope(this.prefixNamespaceMap -- prefixes)
Returns this.prefixNamespaceMap.values.toSet.
Returns this.prefixNamespaceMap.values.toSet. Hence, the "XML namespace" is not returned.
Returns true if this Scope is not empty.
Returns one of the prefixes for the given namespace URI, if any, and otherwise falling back to a prefix (or exception) computed by the 2nd parameter.
Returns one of the prefixes for the given namespace URI, if any, and otherwise falling back to a prefix (or exception) computed by the 2nd parameter. The result may be the empty string for the default namespace, if the default namespace is indeed equal to the passed namespace URI. The result is "xml" if the namespace URI is "http://www.w3.org/XML/1998/namespace".
If the given namespace is the default namespace, but if there is also a non-empty prefix for the namespace, that non-empty prefix is returned. Otherwise, if the given namespace is the default namespace, the empty string is returned.
The prefix fallback is only used if prefixesForNamespace(namespaceUri).isEmpty. If the fallback prefix conflicts
with an already used prefix (including ""), an exception is thrown.
This method can be handy when "inserting" an "element" into a parent tree, if one wants to reuse prefixes of the parent tree.
Returns the prefixes for the given namespace URI.
Returns the prefixes for the given namespace URI. The result includes the empty string for the default namespace, if the default namespace is indeed equal to the passed namespace URI. The result does not include "xml" for the implicit "xml" namespace (with namespace URI http://www.w3.org/XML/1998/namespace).
The result is equivalent to:
this.inverse.getOrElse(namespaceUri, Set())
This method can be handy when "inserting" an "element" into a parent tree, if one wants to reuse prefixes of the parent tree.
Relativizes the given Scope against this Scope, returning a Declarations object.
Relativizes the given Scope against this Scope, returning a Declarations object.
Inspired by java.net.URI, which has a similar method for URIs.
Resolves the given declarations against this Scope, returning an "updated" Scope.
Resolves the given declarations against this Scope, returning an "updated" Scope.
Inspired by java.net.URI, which has a similar method for URIs.
Returns resolveQNameOption(qname)(enameProvider).get.
Tries to resolve the given QName against this Scope, returning None for prefixed names whose prefixes are unknown
to this Scope.
Tries to resolve the given QName against this Scope, returning None for prefixed names whose prefixes are unknown
to this Scope.
Note that the subScopeOf relation keeps the resolveQNameOption result the same, provided there is no default namespace.
That is, if scope1.withoutDefaultNamespace.subScopeOf(scope2.withoutDefaultNamespace), then for each QName qname
such that scope1.withoutDefaultNamespace.resolveQNameOption(qname).isDefined, we have:
scope1.withoutDefaultNamespace.resolveQNameOption(qname) == scope2.withoutDefaultNamespace.resolveQNameOption(qname)
Returns an adapted copy of this Scope, but retaining only the default namespace, if any
Returns true if this is a subscope of the given parameter Scope.
Returns true if this is a subscope of the given parameter Scope. A Scope is considered subscope of itself.
Returns true if this is a superscope of the given parameter Scope.
Returns true if this is a superscope of the given parameter Scope. A Scope is considered superscope of itself.
Creates a String representation of this Scope, as it is shown in XML
Returns an adapted copy of this Scope, but without the default namespace, if any
Scope mapping prefixes to namespace URIs, as well as holding an optional default namespace. In other words, in-scope namespaces.
The purpose of a eu.cdevreeze.yaidom.core.Scope is to resolve eu.cdevreeze.yaidom.core.QNames as eu.cdevreeze.yaidom.core.ENames.
For example, consider the following XML:
Then the (only) author element has the following scope:
After all, the root element has the following scope:
which is the same as:
The (only) book element has no namespace declarations, so it has the same scope. That is also true for the authors element inside the book element. The (only) author element introduces a new namespace, and its scope is as follows:
which is indeed:
The author element
QName("auth:Author")has (optional) resolved name:which is:
A
Scopemust not contain prefix "xmlns" and must not contain namespace URI "http://www.w3.org/2000/xmlns/". Moreover, aScopemust not contain the XML namespace (prefix "xml", namespace URI "http://www.w3.org/XML/1998/namespace").The Scope is backed by a map from prefixes (or the empty string for the default namespace) to (non-empty) namespace URIs.
This class depends on Declarations, but not the other way around.
Concise querying using QNames which are converted to ENames
EName-based querying is more robust than QName-based querying, but ENames are more verbose than QNames. We can get the best of both ENames and QNames by querying using (concise) QNames, and by using a Scope converting them to (stable) ENames.
For example:
This is exactly equivalent to the following query:
Scope more formally
In order to get started using the class, this more formal section can safely be skipped. On the other hand, this section may provide a deeper understanding of the class.
Method
resolveresolves aDeclarationsagainst this Scope, returning a new Scope. It could be defined by the following equality:scope.resolve(declarations) == { val m = (scope.prefixNamespaceMap ++ declarations.withoutUndeclarations.prefixNamespaceMap) -- declarations.retainingUndeclarations.prefixNamespaceMap.keySet Scope(m) }The actual implementation may be more efficient than that, but it is consistent with this definition.
Method
relativizerelativizes a Scope against this Scope, returning aDeclarations. It could be defined by the following equality:scope1.relativize(scope2) == { val declared = scope2.prefixNamespaceMap filter { case (pref, ns) => scope1.prefixNamespaceMap.getOrElse(pref, "") != ns } val undeclared = scope1.prefixNamespaceMap.keySet -- scope2.prefixNamespaceMap.keySet Declarations(declared) ++ Declarations.undeclaring(undeclared) }Again, the actual implementation may be more efficient than that, but it is consistent with this definition.
1. Property about two Scopes, and its proof
Methods
relativizeandresolveobey the following equality:Below follows the proof. We distinguish among the following cases:
phas the same mappings inscope1andscope2phas different mappings inscope1andscope2ponly belongs toscope1ponly belongs toscope2pbelongs to neither scopePrefix
pcan be the empty string, for the default namespace. For each of these cases, we prove that:Since there are no other cases, that would complete the proof.
If prefix
phas the same mappings in both scopes, then:so the following equalities hold:
so:
If prefix
phas different mappings in both scopes, then:If prefix
ponly belongs toscope1, then:if prefix
ponly belongs toscope2, then:if prefix
pbelongs to neither scope, then obviously:scope1.resolve(scope1.relativize(scope2)).prefixNamespaceMap.get(p).isEmpty scope1.resolve(scope1.relativize(scope2)).prefixNamespaceMap.get(p) == scope2.prefixNamespaceMap.get(p) // both empty2. Property about Scope and Declarations
Methods
relativizeandresolvealso obey the following equality:where
scope.minimize(declarations)is defined by the following equality:scope.minimize(declarations) == { val declared = declarations.withoutUndeclarations.prefixNamespaceMap filter { case (pref, ns) => scope.prefixNamespaceMap.getOrElse(pref, "") != ns } val undeclared = declarations.retainingUndeclarations.prefixNamespaceMap.keySet.intersect(scope.prefixNamespaceMap.keySet) Declarations(declared) ++ Declarations.undeclaring(undeclared) }It can be proven by distinguishing among the following cases:
phas the same mappings inscopeanddeclarations(so no undeclaration)phas different mappings inscopeanddeclarations(but no undeclaration)pbelongs toscopeand is undeclared indeclarationsponly belongs toscope, and does not occur indeclarationsponly occurs indeclarations, without being undeclared, and does not occur inscopeponly occurs indeclarations, in an undeclaration, and does not occur inscopepneither occurs inscopenor indeclarationsPrefix
pcan be the empty string, for the default namespace. For each of these cases, it can be proven that:Since there are no other cases, that would complete the proof. The proof itself is left as an exercise for the reader, as they say.
This and the preceding (proven) property are analogous to corresponding properties in the
URIclass.