net.sf.saxon.s9api.QName Maven / Gradle / Ivy
Show all versions of Saxon-HE Show documentation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2023 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package net.sf.saxon.s9api;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.NameChecker;
import net.sf.saxon.om.NamespaceUri;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.trans.XPathException;
import java.util.Objects;
/**
* The QName class represents an instance of xs:QName, as defined in the XPath 2.0 data model.
* Internally, it has three components, a namespace URI, a local name, and a prefix. The prefix
* is intended to be used only when converting the value back to a string.
* This class also defines a number of QName-valued constants relating to built-in types in
* XML Schema
* A QName is immutable.
* Note that a QName is not itself an {@link XdmItem} in this model; however it can be wrapped in an
* XdmItem.
*/
public class QName {
private final StructuredQName sqName;
/**
* Construct a QName using a namespace prefix, a namespace URI, and a local name (in that order).
* This constructor does not check that the components of the QName are lexically valid.
*
* @param prefix The prefix of the name. Use either the string "" or null for names that have
* no prefix (that is, they are in the default namespace)
* @param uri The namespace URI. Use either the string "" or null for names that are not in any namespace.
* @param localName The local part of the name
*/
public QName(String prefix, String uri, String localName) {
sqName = new StructuredQName(prefix, NamespaceUri.of(uri), localName);
}
/**
* Construct a QName using a namespace URI and a lexical representation. The lexical representation
* may be a local name on its own, or it may be in the form prefix:local-name.
* This constructor does not check that the components of the QName are lexically valid.
*
* @param uri The namespace URI. Use either the string "" or null for names that are not in any namespace.
* @param lexical Either the local part of the name, or the prefix and local part in the format prefix:local
*/
public QName(String uri, String lexical) {
uri = (uri == null ? "" : uri);
int colon = lexical.indexOf(':');
if (colon < 0) {
sqName = new StructuredQName("", NamespaceUri.of(uri), lexical);
} else {
String prefix = lexical.substring(0, colon);
String local = lexical.substring(colon + 1);
sqName = new StructuredQName(prefix, NamespaceUri.of(uri), local);
}
}
/**
* Construct a QName from a localName alone. The localName must not contain a colon.
* The resulting QName represents a name in no namespace (which therefore has no prefix)
*
* @param localName The local name. This must be a valid NCName, in particular it must contain no colon
*/
public QName(String localName) {
int colon = localName.indexOf(':');
if (colon < 0) {
sqName = new StructuredQName("", NamespaceUri.NULL, localName);
} else {
throw new IllegalArgumentException("Local name contains a colon");
}
}
/**
* Construct a QName from a lexical QName, supplying an element node whose
* in-scope namespaces are to be used to resolve any prefix contained in the QName.
* This constructor checks that the components of the QName are
* lexically valid.
* If the lexical QName has no prefix, the name is considered to be in the
* default namespace, as defined by xmlns="..."
.
* If the prefix of the lexical QName is not in scope, returns null.
*
* @param lexicalQName The lexical QName, in the form prefix:local
* or simply local
. The EQName syntax "Q{uri}local"
* and the ClarkName syntax "{uri}local" are also accepted.
* @param element The element node whose in-scope namespaces are to be used
* to resolve the prefix part of the lexical QName.
* @throws IllegalArgumentException If the prefix of the lexical QName is not in scope
* or if the lexical QName is invalid (for example, if it contains invalid characters)
*/
public QName(String lexicalQName, XdmNode element) {
if (lexicalQName.startsWith("{")) {
lexicalQName = "Q" + lexicalQName;
}
try {
NodeInfo node = element.getUnderlyingValue();
sqName = StructuredQName.fromLexicalQName((lexicalQName), true,
true, node.getAllNamespaces());
} catch (XPathException err) {
throw new IllegalArgumentException(err);
}
}
/**
* Construct a QName from a JAXP QName object
*
* @param qName the JAXP QName object
*/
public QName(javax.xml.namespace.QName qName) {
sqName = new StructuredQName(qName.getPrefix(), NamespaceUri.of(qName.getNamespaceURI()), qName.getLocalPart());
}
/**
* Construct a QName from a StructuredQName
*
* @param sqName the StructuredQName
*/
public QName(StructuredQName sqName) {
this.sqName = Objects.requireNonNull(sqName);
}
/**
* Factory method to construct a QName from a string containing the expanded
* QName in Clark notation, that is, {uri}local
* The prefix part of the QName
will be set to an empty string.
*
* @param expandedName The URI in Clark notation: {uri}local
if the
* name is in a namespace, or simply local
if not.
* @return the QName corresponding to the supplied name in Clark notation. This will always
* have an empty prefix.
* @throws IllegalArgumentException if the format of the supplied name is incorrect
*/
public static QName fromClarkName(String expandedName) throws IllegalArgumentException {
String namespaceURI;
String localName;
if (expandedName == null || expandedName.isEmpty()) {
throw new IllegalArgumentException("Supplied Clark name is null or empty");
}
if (expandedName.charAt(0) == '{') {
int closeBrace = expandedName.indexOf('}');
if (closeBrace < 0) {
throw new IllegalArgumentException("No closing '}' in Clark name");
}
namespaceURI = expandedName.substring(1, closeBrace);
if (closeBrace == expandedName.length()) {
throw new IllegalArgumentException("Missing local part in Clark name");
}
localName = expandedName.substring(closeBrace + 1);
} else {
namespaceURI = "";
localName = expandedName;
}
return new QName("", namespaceURI, localName);
}
/**
* Factory method to construct a QName from a string containing the expanded
* QName in EQName notation, that is, Q{uri}local
* The prefix part of the QName
will be set to an empty string.
*
* @param expandedName The URI in EQName notation: Q{uri}local
if the
* name is in a namespace. For a name in no namespace, either of the
* forms Q{}local
or simply local
are accepted.
* @return the QName corresponding to the supplied name in EQName notation. This will always
* have an empty prefix.
*/
public static QName fromEQName(String expandedName) {
String namespaceURI;
String localName;
if (expandedName.charAt(0) == 'Q' && expandedName.charAt(1) == '{') {
int closeBrace = expandedName.indexOf('}');
if (closeBrace < 0) {
throw new IllegalArgumentException("No closing '}' in EQName");
}
namespaceURI = expandedName.substring(2, closeBrace);
if (closeBrace == expandedName.length()) {
throw new IllegalArgumentException("Missing local part in EQName");
}
localName = expandedName.substring(closeBrace + 1);
} else {
namespaceURI = "";
localName = expandedName;
}
return new QName("", namespaceURI, localName);
}
/**
* Validate the QName against the XML 1.0 or XML 1.1 rules for valid names.
*
* @param processor The Processor in which the name is to be validated.
* This was at one time used to determine whether the
* XML 1.0 or XML 1.1 rules for forming names are used. However,
* the XML 1.0 and 1.1 rules are now aligned, so this argument
* is no longer used.
* @return true if the name is valid, false if not
*/
public boolean isValid(Processor processor) {
String prefix = getPrefix();
if (!prefix.isEmpty() && !NameChecker.isValidNCName(prefix)) {
return false;
}
return NameChecker.isValidNCName(getLocalName());
}
/**
* Get the prefix of the QName. This plays no role in operations such as comparison
* of QNames for equality, but is retained (as specified in XPath) so that a string representation
* can be reconstructed.
* Returns the zero-length string in the case of a QName that has no prefix.
*
* @return the prefix part of the QName, or "" if the name has no known prefix
*/
public String getPrefix() {
return sqName.getPrefix();
}
/**
* The namespace URI of the QName, as a string. Returns the zero-length string if the
* QName is not in a namespace.
*
* @return the namespace part of the QName, or "" for a name in no namespace
*/
public String getNamespace() {
return sqName.getNamespaceUri().toString();
}
/**
* The namespace URI of the QName, as a string. Returns the zero-length string if the
* QName is not in a namespace.
*
* Retained for backwards compatibility; deprecated.
*
* @return the namespace part of the QName, or "" for a name in no namespace
* @deprecated since 12.0 - use {@link #getNamespaceUri()} or {@link #getNamespace()}
*/
@Deprecated
public String getNamespaceURI() {
return sqName.getNamespaceUri().toString();
}
/**
* The namespace URI of the QName. Returns {@link NamespaceUri#NULL} (the zero-length string) if the
* QName is not in a namespace.
*
* @return the namespace part of the QName, or NamespaceUri#NULL for a name in no namespace
*/
public NamespaceUri getNamespaceUri() {
return sqName.getNamespaceUri();
}
/**
* The local part of the QName
*
* @return the local part of the QName
*/
public String getLocalName() {
return sqName.getLocalPart();
}
/**
* The expanded name, as a string using the notation devised by James Clark.
* If the name is in a namespace, the resulting string takes the form {uri}local
.
* Otherwise, the value is the local part of the name.
*
* @return the name in Clark notation. If the name is not in a namespace, returns the
* local part of the name. Otherwise returns the concatenation of "{", the namespace part
* of the QName, "}", and the local part of the QName.
*/
public String getClarkName() {
NamespaceUri uri = getNamespaceUri();
if (uri.isEmpty()) {
return getLocalName();
} else {
return "{" + uri + "}" + getLocalName();
}
}
/*
* The expanded name, as a string using the notation defined by the EQName production in XPath 3.0.
* If the name is in a namespace, the resulting string takes the form Q{uri}local
.
* Otherwise, the value is the local part of the name.
*
*/
public String getEQName() {
NamespaceUri uri = getNamespaceUri();
if (uri.isEmpty()) {
return getLocalName();
} else {
return "Q{" + uri + "}" + getLocalName();
}
}
/**
* Convert the value to a string. The resulting string is the lexical form of the QName,
* using the original prefix if there was one.
*/
public String toString() {
return sqName.getDisplayName();
}
/**
* Get a hash code for the QName, to support equality matching. This supports the
* semantics of equality, which considers only the namespace URI and local name, and
* not the prefix.
*
* @return a hashCode for the QName
*/
public int hashCode() {
return sqName.hashCode();
}
/**
* Test whether two QNames are equal. This supports the
* semantics of equality, which considers only the namespace URI and local name, and
* not the prefix.
*
* @return true if the namespace URIs are equal and the local parts are equal, when
* compared character-by-character.
*/
public boolean equals(Object other) {
return other instanceof QName && sqName.equals(((QName) other).sqName);
}
/**
* Get the underlying StructuredQName
*
* @return the underlying StructuredQName
*/
public StructuredQName getStructuredQName() {
return sqName;
}
/**
* QName denoting the schema type xs:string *
*/
public static final QName XS_STRING =
new QName("xs", NamespaceConstant.SCHEMA, "string");
/**
* QName denoting the schema type xs:boolean *
*/
public static final QName XS_BOOLEAN =
new QName("xs", NamespaceConstant.SCHEMA, "boolean");
/**
* QName denoting the schema type xs:decimal *
*/
public static final QName XS_DECIMAL =
new QName("xs", NamespaceConstant.SCHEMA, "decimal");
/**
* QName denoting the schema type xs:float *
*/
public static final QName XS_FLOAT =
new QName("xs", NamespaceConstant.SCHEMA, "float");
/**
* QName denoting the schema type xs:double *
*/
public static final QName XS_DOUBLE =
new QName("xs", NamespaceConstant.SCHEMA, "double");
/**
* QName denoting the schema type xs:duration *
*/
public static final QName XS_DURATION =
new QName("xs", NamespaceConstant.SCHEMA, "duration");
/**
* QName denoting the schema type xs:dateTime *
*/
public static final QName XS_DATE_TIME =
new QName("xs", NamespaceConstant.SCHEMA, "dateTime");
/**
* QName denoting the schema type xs:time *
*/
public static final QName XS_TIME =
new QName("xs", NamespaceConstant.SCHEMA, "time");
/**
* QName denoting the schema type xs:date *
*/
public static final QName XS_DATE =
new QName("xs", NamespaceConstant.SCHEMA, "date");
/**
* QName denoting the schema type xs:gYearMonth *
*/
public static final QName XS_G_YEAR_MONTH =
new QName("xs", NamespaceConstant.SCHEMA, "gYearMonth");
/**
* QName denoting the schema type xs:gYear *
*/
public static final QName XS_G_YEAR =
new QName("xs", NamespaceConstant.SCHEMA, "gYear");
/**
* QName denoting the schema type xs:gMonthDay *
*/
public static final QName XS_G_MONTH_DAY =
new QName("xs", NamespaceConstant.SCHEMA, "gMonthDay");
/**
* QName denoting the schema type xs:gDay *
*/
public static final QName XS_G_DAY =
new QName("xs", NamespaceConstant.SCHEMA, "gDay");
/**
* QName denoting the schema type xs:gMonth *
*/
public static final QName XS_G_MONTH =
new QName("xs", NamespaceConstant.SCHEMA, "gMonth");
/**
* QName denoting the schema type xs:hexBinary *
*/
public static final QName XS_HEX_BINARY =
new QName("xs", NamespaceConstant.SCHEMA, "hexBinary");
/**
* QName denoting the schema type xs:base64Binary *
*/
public static final QName XS_BASE64_BINARY =
new QName("xs", NamespaceConstant.SCHEMA, "base64Binary");
/**
* QName denoting the schema type xs:anyURI *
*/
public static final QName XS_ANY_URI =
new QName("xs", NamespaceConstant.SCHEMA, "anyURI");
/**
* QName denoting the schema type xs:QName *
*/
public static final QName XS_QNAME =
new QName("xs", NamespaceConstant.SCHEMA, "QName");
/**
* QName denoting the schema type xs:NOTATION *
*/
public static final QName XS_NOTATION =
new QName("xs", NamespaceConstant.SCHEMA, "NOTATION");
/**
* QName denoting the schema type xs:integer *
*/
public static final QName XS_INTEGER =
new QName("xs", NamespaceConstant.SCHEMA, "integer");
/**
* QName denoting the schema type xs:nonPositiveInteger *
*/
public static final QName XS_NON_POSITIVE_INTEGER =
new QName("xs", NamespaceConstant.SCHEMA, "nonPositiveInteger");
/**
* QName denoting the schema type xs:negativeInteger *
*/
public static final QName XS_NEGATIVE_INTEGER =
new QName("xs", NamespaceConstant.SCHEMA, "negativeInteger");
/**
* QName denoting the schema type xs:long *
*/
public static final QName XS_LONG =
new QName("xs", NamespaceConstant.SCHEMA, "long");
/**
* QName denoting the schema type xs:int *
*/
public static final QName XS_INT =
new QName("xs", NamespaceConstant.SCHEMA, "int");
/**
* QName denoting the schema type xs:short *
*/
public static final QName XS_SHORT =
new QName("xs", NamespaceConstant.SCHEMA, "short");
/**
* QName denoting the schema type xs:byte *
*/
public static final QName XS_BYTE =
new QName("xs", NamespaceConstant.SCHEMA, "byte");
/**
* QName denoting the schema type xs:nonNegativeInteger *
*/
public static final QName XS_NON_NEGATIVE_INTEGER =
new QName("xs", NamespaceConstant.SCHEMA, "nonNegativeInteger");
/**
* QName denoting the schema type xs:positiveInteger *
*/
public static final QName XS_POSITIVE_INTEGER =
new QName("xs", NamespaceConstant.SCHEMA, "positiveInteger");
/**
* QName denoting the schema type xs:unsignedLong *
*/
public static final QName XS_UNSIGNED_LONG =
new QName("xs", NamespaceConstant.SCHEMA, "unsignedLong");
/**
* QName denoting the schema type xs:unsignedInt *
*/
public static final QName XS_UNSIGNED_INT =
new QName("xs", NamespaceConstant.SCHEMA, "unsignedInt");
/**
* QName denoting the schema type xs:unsignedShort *
*/
public static final QName XS_UNSIGNED_SHORT =
new QName("xs", NamespaceConstant.SCHEMA, "unsignedShort");
/**
* QName denoting the schema type xs:unsignedByte *
*/
public static final QName XS_UNSIGNED_BYTE =
new QName("xs", NamespaceConstant.SCHEMA, "unsignedByte");
/**
* QName denoting the schema type xs:normalizedString *
*/
public static final QName XS_NORMALIZED_STRING =
new QName("xs", NamespaceConstant.SCHEMA, "normalizedString");
/**
* QName denoting the schema type xs:token *
*/
public static final QName XS_TOKEN =
new QName("xs", NamespaceConstant.SCHEMA, "token");
/**
* QName denoting the schema type xs:language *
*/
public static final QName XS_LANGUAGE =
new QName("xs", NamespaceConstant.SCHEMA, "language");
/**
* QName denoting the schema type xs:NMTOKEN *
*/
public static final QName XS_NMTOKEN =
new QName("xs", NamespaceConstant.SCHEMA, "NMTOKEN");
/**
* QName denoting the schema type xs:NMTOKENS *
*/
public static final QName XS_NMTOKENS =
new QName("xs", NamespaceConstant.SCHEMA, "NMTOKENS");
/**
* QName denoting the schema type xs:Name *
*/
public static final QName XS_NAME =
new QName("xs", NamespaceConstant.SCHEMA, "Name");
/**
* QName denoting the schema type xs:NCName *
*/
public static final QName XS_NCNAME =
new QName("xs", NamespaceConstant.SCHEMA, "NCName");
/**
* QName denoting the schema type xs:ID *
*/
public static final QName XS_ID =
new QName("xs", NamespaceConstant.SCHEMA, "ID");
/**
* QName denoting the schema type xs:IDREF *
*/
public static final QName XS_IDREF =
new QName("xs", NamespaceConstant.SCHEMA, "IDREF");
/**
* QName denoting the schema type xs:IDREFS *
*/
public static final QName XS_IDREFS =
new QName("xs", NamespaceConstant.SCHEMA, "IDREFS");
/**
* QName denoting the schema type xs:ENTITY *
*/
public static final QName XS_ENTITY =
new QName("xs", NamespaceConstant.SCHEMA, "ENTITY");
/**
* QName denoting the schema type xs:ENTITIES *
*/
public static final QName XS_ENTITIES =
new QName("xs", NamespaceConstant.SCHEMA, "ENTITIES");
/**
* QName denoting the schema type xs:untyped *
*/
public static final QName XS_UNTYPED =
new QName("xs", NamespaceConstant.SCHEMA, "untyped");
/**
* QName denoting the schema type xs:untypedAtomic *
*/
public static final QName XS_UNTYPED_ATOMIC =
new QName("xs", NamespaceConstant.SCHEMA, "untypedAtomic");
/**
* QName denoting the schema type xs:anyAtomicType *
*/
public static final QName XS_ANY_ATOMIC_TYPE =
new QName("xs", NamespaceConstant.SCHEMA, "anyAtomicType");
/**
* QName denoting the schema type xs:yearMonthDuration *
*/
public static final QName XS_YEAR_MONTH_DURATION =
new QName("xs", NamespaceConstant.SCHEMA, "yearMonthDuration");
/**
* QName denoting the schema type xs:dayTimeDuration *
*/
public static final QName XS_DAY_TIME_DURATION =
new QName("xs", NamespaceConstant.SCHEMA, "dayTimeDuration");
/**
* QName denoting the schema type xs:dateTimeStamp *
*/
public static final QName XS_DATE_TIME_STAMP =
new QName("xs", NamespaceConstant.SCHEMA, "dateTimeStamp");
}