@openxmldev/linq-to-xml
Version:
LINQ to XML for TypeScript
107 lines • 3.67 kB
JavaScript
/**
* @author Thomas Barnekow
* @license MIT
*/
import { Inserter, InvalidOperationException, LinqElements, XElement, XObject, } from './internal.js';
/**
* Represents an XML node.
*/
export class XNode extends XObject {
constructor() {
super();
/** @internal */
this._next = null;
}
/**
* Gets the next sibling node of this node.
*
* If this node does not have a parent, or if there is no next node,
* then this property returns null.
*/
get nextNode() {
return this._parent === null || this._parent._content === this
? null
: this._next;
}
/**
* Gets the previous sibling node of this node.
*
* If this property does not have a parent, or if there is no previous node,
* then this property returns null.
*/
get previousNode() {
if (this._parent === null)
return null;
// At this point, we know that the parent XContainer has XNode content.
// We start with p being null and n being the first node.
let previousNode = null;
let nextNode = this._parent._content._next;
while (nextNode !== this) {
previousNode = nextNode;
nextNode = nextNode._next;
}
return previousNode;
}
/**
* Returns the collection of the ancestor elements for this node.
*
* @param name The optional name of the ancestor elements to find.
* @returns The ancestor elements of this node.
*/
ancestors(name) {
return name === null
? new LinqElements(XElement.emptySequence)
: new LinqElements(getAncestors(this, name !== null && name !== void 0 ? name : null, false));
}
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
appendText(_sb) {
// No operation
}
/**
* Removes this `XNode` from the underlying XML tree.
*/
remove() {
this.getParentXContainerOrThrow().removeNode(this);
}
/**
* Replaces this node with the specified content.
*
* @param content Content that replaces this node.
*/
replaceWith(...content) {
const parent = this.getParentXContainerOrThrow();
// Get the previous sibling node as the anchor for inserting the replacement
// content. That anchor will be null if the this node is the parent's only
// child node.
let previousNode = parent._content;
while (previousNode._next !== this)
previousNode = previousNode._next;
if (previousNode === parent._content)
previousNode = null;
parent.removeNode(this);
if (previousNode !== null && previousNode._parent !== parent) {
throw new InvalidOperationException('This operation was corrupted by external code.');
}
if (content.length > 0) {
// Add the replacement content after the previous (anchor) node.
new Inserter(parent, previousNode).add(content.length === 1 ? content[0] : content);
}
}
getParentXContainerOrThrow() {
if (this._parent === null) {
throw new InvalidOperationException('The parent is missing.');
}
return this._parent;
}
}
/** @internal */
export function* getAncestors(node, name, self) {
let e = (self ? node : node._parent);
while (e !== null) {
if (name === null || e._name === name)
yield e;
e = e._parent;
}
}
//# sourceMappingURL=XNode.js.map