UNPKG

fontoxpath

Version:

A minimalistic XPath 3.1 engine in JavaScript

96 lines (85 loc) 2.59 kB
import TestAbstractExpression from './TestAbstractExpression'; import Specificity from '../Specificity'; import isSubtypeOf from '../dataTypes/isSubtypeOf'; /** * @extends {./TestAbstractExpression} */ class NameTest extends TestAbstractExpression { /** * @param {?string} prefix * @param {?string} namespaceURI * @param {string} localName * @param {{kind: ?number}} [options=] */ constructor (prefix, namespaceURI, localName, options = { kind: null }) { const specificity = {}; if (localName !== '*') { specificity[Specificity.NODENAME_KIND] = 1; } if (options.kind !== null) { specificity[Specificity.NODETYPE_KIND] = 1; } super(new Specificity(specificity)); this._localName = localName; this._namespaceURI = namespaceURI; this._prefix = prefix; this._kind = options.kind; } evaluateToBoolean (dynamicContext, node) { const nodeIsElement = isSubtypeOf(node.type, 'element()'); const nodeIsAttribute = isSubtypeOf(node.type, 'attribute()'); if (!nodeIsElement && !nodeIsAttribute) { return false; } if (this._kind !== null && ((this._kind === 1 && !nodeIsElement) || this._kind === 2 && !nodeIsAttribute)) { return false; } // Easy cases first if (this._prefix === null && this._localName === '*') { return true; } if (this._prefix === '*') { if (this._localName === '*') { return true; } return this._localName === node.value.localName; } if (this._localName !== '*') { if (this._localName !== node.value.localName) { return false; } } let resolvedNamespaceURI; if (this._namespaceURI !== null) { resolvedNamespaceURI = this._namespaceURI || null; } else if (this._prefix === null) { // An unprefixed QName, when used as a name test on an axis whose principal node kind is element, // has the namespace URI of the default element/type namespace in the expression context; // otherwise, it has no namespace URI. if (nodeIsElement) { resolvedNamespaceURI = dynamicContext.resolveNamespacePrefix(''); } else { resolvedNamespaceURI = null; } } else { resolvedNamespaceURI = dynamicContext.resolveNamespacePrefix(this._prefix); if (!resolvedNamespaceURI) { throw new Error(`XPST0081: The prefix ${this._prefix} could not be resolved.`); } } return node.value.namespaceURI === resolvedNamespaceURI; } getBucket () { if (this._localName === '*') { if (this._kind === null) { return null; } return `type-${this._kind}`; } return 'name-' + this._localName; } } export default NameTest;