UNPKG

@openxmldev/linq-to-xml

Version:
171 lines 6.29 kB
/** * @author Thomas Barnekow * @license MIT */ import { ArgumentException } from '@tsdotnet/exceptions'; import { InvalidOperationException, XObject, XContainer, XElement, XName, XNamespace, } from './internal.js'; /** * Represents an XML attribute. */ export class XAttribute extends XObject { /** * Initializes a new instance. * * @param name The name of the attribute. * @param value The value of the attribute. */ constructor(name, value) { super(); const xname = name instanceof XName ? name : XName.get(name); const stringValue = XContainer.getStringValue(value); XAttribute.validateAttribute(xname, stringValue); this._name = xname; this._value = stringValue; this._next = null; } static validateAttribute(name, value) { // The following constraints apply for namespace declarations. const namespaceName = name.namespaceName; if (namespaceName === XNamespace.xmlnsPrefixNamespaceName) { if (value.length === 0) { throw new Error('The empty namespace name can only be declared by the default namespace declaration.'); } else if (value === XNamespace.xmlPrefixNamespaceName) { if (name.localName !== 'xml') { throw new ArgumentException('name', '"http://www.w3.org/XML/1998/namespace" can only be declared by the "xml" prefix'); } } else if (value === XNamespace.xmlnsPrefixNamespaceName) { throw new ArgumentException('value', '"http://www.w3.org/2000/xmlns/" must not be declared by any namespace declaration.'); } else { const localName = name.localName; if (localName === 'xml') { // At this point, the attribute name is xmlns:xml but the value is not equal // to the XML prefix namespace name. throw new ArgumentException('name', 'No other namespace name can be declared by the "xml" prefix namespace declaration.'); } else if (localName === 'xmlns') { throw new ArgumentException('name', 'The "xmlns" prefix must not be declared.'); } } } else if (namespaceName.length === 0 && name.localName === 'xmlns') { if (value === XNamespace.xmlPrefixNamespaceName) { throw new ArgumentException('name', '"http://www.w3.org/XML/1998/namespace" can only be declared by the "xml" prefix namespace declaration.'); } else if (value === XNamespace.xmlnsPrefixNamespaceName) { throw new ArgumentException('name', '"http://www.w3.org/2000/xmlns/" must not be declared by any namespace declaration.'); } } } /** * Gets a value indicating if this attribute is a namespace declaration. */ get isNamespaceDeclaration() { const namespaceName = this._name.namespaceName; // Deal with xmlns="namespaceName". if (namespaceName.length === 0) { return this._name.localName === 'xmlns'; } // Deal with xmlns:prefix="namespaceName". return namespaceName === XNamespace.xmlnsPrefixNamespaceName; } /** * Gets the name of this attribute. */ get name() { return this._name; } /** * Gets the next attribute of the parent element. */ get nextAttribute() { return this._parent instanceof XElement && this._parent.lastAttribute !== this ? this._next : null; } /** * Gets the value of this attribute. */ get value() { return this._value; } /** * Sets the value of this attribute. */ set value(value) { XAttribute.validateAttribute(this._name, value); this._value = value; } /** @internal */ getPrefixOfNamespace(ns) { const namespaceName = ns.namespaceName; if (namespaceName.length == 0) return ''; if (this._parent !== null) { return this._parent.getPrefixOfNamespace(ns); } if (namespaceName === XNamespace.xmlPrefixNamespaceName) return 'xml'; if (namespaceName === XNamespace.xmlnsPrefixNamespaceName) return 'xmlns'; return null; } /** * Removes this attribute from its parent. */ remove() { if (this._parent === null) { throw new InvalidOperationException('The parent is missing.'); } this._parent.removeAttribute(this); } /** * Gets the XML text representation of an attribute and its value. * * @returns The XML text representation of an attribute and its value. */ toString() { const name = this._name; const prefix = this.getPrefixOfNamespace(name.namespace); const qualifiedName = prefix ? `${prefix}:${name.localName}` : name.localName; const value = this.transformXmlEntities(this._value); return `${qualifiedName}="${value}"`; } /** @internal */ transformXmlEntities(value) { let transformedValue = ''; for (let index = 0; index < value.length; index++) { const code = value.charCodeAt(index); if (code === 34) { transformedValue += '&quot;'; } else if (code === 38) { transformedValue += '&amp;'; } else if (code === 60) { transformedValue += '&lt;'; } else if (code === 62) { transformedValue += '&gt;'; } else { transformedValue += value.charAt(index); } } return transformedValue; } } /** * Gets an empty collection of attributes. */ XAttribute.emptySequence = { *[Symbol.iterator]() { // Do not return anything. }, }; //# sourceMappingURL=XAttribute.js.map