File

projects/wms-framework/src/lib/xml/xmlclasses.ts

Description

Xml document

Extends

XContainer

Index

Properties
Methods

Constructor

constructor(doc: Document)

Creates an instance of XDocument.

Parameters :
Name Type Optional
doc Document No

Properties

Protected contents
Type : XNode[]
Default value : []
Inherited from XContainer
Defined in XContainer:112

Sequence of elements

parent
Type : XContainer
Inherited from XObject
Defined in XObject:38

Parent of current element

Methods

Static parse
parse(literalXml: string)

Parse XML document from an string

Parameters :
Name Type Optional
literalXml string No
Returns : XDocument

{XDocument}

Public toString
toString()

Converts the document to a string

Returns : string

{string}

Public Add
Add(content: object)
Inherited from XContainer
Defined in XContainer:243

Adds child to the current element

Parameters :
Name Type Optional
content object No
Returns : void
Public Descendants
Descendants(elementName?: string)
Inherited from XContainer
Defined in XContainer:206

Retrieves the descendants with the given name

Parameters :
Name Type Optional
elementName string Yes
Returns : Iterable<XElement>

{Iterable}

Public element
element(elementName: string)
Inherited from XContainer
Defined in XContainer:147

Retrieves an element with the given name

Parameters :
Name Type Optional
elementName string No
Returns : XElement

{XElement}

Public elements
elements(elementName?: string)
Inherited from XContainer
Defined in XContainer:164

Retrieves the sequence of elements

Parameters :
Name Type Optional
elementName string Yes
Returns : Iterable<XElement>

{Iterable}

Public getContents
getContents()
Inherited from XContainer
Defined in XContainer:256

Get content array

Returns : XNode[]

{XNode[]}

Public GetDescendantsByName
GetDescendantsByName(container: XContainer, elementName: string)
Inherited from XContainer
Defined in XContainer:221

Gets descendants by name

Parameters :
Name Type Optional
container XContainer No
elementName string No
Returns : Iterable<XElement>

{Iterable}

Protected initWith
initWith(elements: Iterable<Node>)
Inherited from XContainer
Defined in XContainer:121

Initialize current element with the given node list

Parameters :
Name Type Optional
elements Iterable<Node> No
Returns : void
Public nodes
nodes()
Inherited from XContainer
Defined in XContainer:182

Gets the sequence of child nodes

Returns : Iterable<XNode>

{Iterable}

Public removeChildElement
removeChildElement(e: XElement)
Inherited from XContainer
Defined in XContainer:192

Removes the given child element

Parameters :
Name Type Optional
e XElement No
Returns : void
import { iuFirstOrDefault, iuOfType } from '../baseframework/collections';
import { XmlWriter } from '../baseframework/XmlWriter';
import { StringWriter } from '../helpers/StreamsSupport';

/**
 * Base class for Xml objects
 *
 * @export
 * @abstract
 * @class XObject
 * @wType System.Xml.Linq.XObject
 * @wNetSupport
 */
export abstract class XObject {
  /**
   * Parent of current element
   *
   * @type {XContainer}
   * @memberof XObject
   * @wProperty Parent
   */
  parent: XContainer;
}

/**
 * Base class for Xml nodes
 *
 * @export
 * @abstract
 * @class XNode
 * @extends {XObject}
 * @wType System.Xml.Linq.XNode
 * @wNetSupport
 */
export abstract class XNode extends XObject {}

/**
 * Xml attributes
 *
 * @export
 * @class XAttribute
 * @extends {XObject}
 * @wType System.Xml.Linq.XAttribute
 * @wNetSupport
 */
export class XAttribute extends XObject {
  /**
   * Creates an instance of XAttribute.
   * @param {string} Name attribute name
   * @param {string} Value attribute value
   * @memberof XAttribute
   */
  constructor(public Name: string, public Value: string) {
    super();
  }
}

/**
 * Node for text
 *
 * @export
 * @class XText
 * @extends {XNode}
 * @wType System.Xml.Linq.XText
 * @wNetSupport
 */
export class XText extends XNode {
  /**
   * Creates an instance of XText.
   * @param {string} value the text
   * @memberof XText
   */
  constructor(public value: string) {
    super();
  }
}

/**
 * Base class for containers
 *
 * @export
 * @abstract
 * @class XContainer
 * @extends {XNode}
 * @wType System.Xml.Linq.XContainer
 * @wNetSupport
 */
export abstract class XContainer extends XNode {
  /**
   * Sequence of elements
   *
   * @protected
   * @type {XNode[]}
   * @memberof XContainer
   */
  protected contents: XNode[] = [];

  /**
   * Initialize current element with the given node list
   *
   * @protected
   * @param {{ length: number;[index: number]: Node }} elements
   * @memberof XContainer
   */
  protected initWith(elements: Iterable<Node>): void {
    for (const e of elements) {
      if (e.nodeType === 1 && e instanceof Element) {
        const newElement = XElement.createFromDOMElement(e);
        newElement.parent = this;
        this.contents.push(newElement);
      } else if (
        e.nodeType == Node.TEXT_NODE &&
        e.nodeValue &&
        e.nodeValue.trim() !== ''
      ) {
        const newElement = new XText(e.nodeValue);
        newElement.parent = this;
        this.contents.push(newElement);
      }
    }
  }

  /**
   * Retrieves an element with the given name
   *
   * @param {string} elementName
   * @return {*}  {XElement}
   * @memberof XContainer
   * @wMethod Element
   */
  public element(elementName: string): XElement {
    for (const e of this.contents) {
      if (e instanceof XElement && e.localName === elementName) {
        return e;
      }
    }
    return null;
  }

  /**
   * Retrieves the sequence of elements
   *
   * @param {string} [elementName]
   * @return {*}  {Iterable<XElement>}
   * @memberof XContainer
   * @wMethod Elements
   */
  public *elements(elementName?: string): Iterable<XElement> {
    for (const e of this.contents) {
      if (
        e instanceof XElement &&
        (typeof elementName === 'undefined' || e.localName === elementName)
      ) {
        yield e;
      }
    }
  }

  /**
   * Gets the sequence of child nodes
   *
   * @return {*}  {Iterable<XNode>}
   * @memberof XContainer
   * @wMethod Nodes
   */
  public nodes(): Iterable<XNode> {
    return this.contents;
  }

  /**
   * Removes the given child element
   *
   * @param {XElement} e
   * @memberof XContainer
   */
  public removeChildElement(e: XElement): void {
    const idx = this.contents.indexOf(e);
    if (idx !== -1) {
      this.contents.splice(idx, 1);
    }
  }

  /**
   *  Retrieves the descendants with the given name
   *
   * @param {string} [elementName]
   * @return {*}  {Iterable<XElement>}
   * @memberof XContainer
   */
  public *Descendants(elementName?: string): Iterable<XElement> {
    if (elementName) {
      yield* this.GetDescendantsByName(this, elementName);
    }
  }

  /**
   * Gets descendants by name
   *
   * @param {XContainer} container
   * @param {string} elementName
   * @return {*}  {Iterable<XElement>}
   * @memberof XContainer
   * @wIgnore
   */
  public *GetDescendantsByName(
    container: XContainer,
    elementName: string
  ): Iterable<XElement> {
    for (const element of container.contents) {
      if (element instanceof XElement) {
        if (element.localName === elementName) {
          yield element;
        }
        if (element.contents.length > 0) {
          yield* this.GetDescendantsByName(element, elementName);
        }
      }
    }
  }

  /**
   * Adds child to the current element
   *
   * @param {object} content
   * @memberof XContainer
   */
  public Add(content: object): void {
    if (content instanceof XNode) {
      content.parent = this;
      this.contents.push(content);
    }
  }

  /**
   * Get content array
   *
   * @return {*}  {XNode[]}
   * @memberof XContainer
   */
  public getContents(): XNode[] {
    return this.contents;
  }
}

/**
 * Xml document
 *
 * @export
 * @class XDocument
 * @extends {XContainer}
 * @wType System.Xml.Linq.XDocument
 * @wNetSupport
 */
export class XDocument extends XContainer {
  /**
   * Creates an instance of XDocument.
   * @param {Document} doc
   * @memberof XDocument
   */
  constructor(doc: Document) {
    super();
    this.initWith([doc.documentElement]);
  }

  /**
   * Parse XML document from an string
   *
   * @static
   * @param {string} literalXml
   * @return {*}  {XDocument}
   * @memberof XDocument
   * @wMethod Parse
   */
  public static parse(literalXml: string): XDocument {
    const parser = new DOMParser();
    const doc = parser.parseFromString(literalXml, 'text/xml');
    return new XDocument(doc);
  }

  /**
   * Converts the document to a string
   *
   * @return {*}  {string}
   * @memberof XDocument
   */
  public toString(): string {
    return serializeXNodeToString(this.contents[0]);
  }
}

/**
 * Xml element
 *
 * @export
 * @class XElement
 * @extends {XContainer}
 * @wType System.Xml.Linq.XElement
 * @wNetSupport
 */
export class XElement extends XContainer {
  private attributes: { [name: string]: string } = {};
  /**
   * Creates an instance of XElement.
   * @param {string} name
   * @param {...unknown[]} contents
   * @memberof XElement
   */
  constructor(private name: string, ...contents: unknown[]) {
    super();
    for (const contentItem of contents) {
      if (typeof contentItem === 'string') {
        this.contents.push(new XText(contentItem));
      } else if (contentItem instanceof XNode) {
        this.contents.push(contentItem);
      }
    }
  }

  /**
   * Get the local name
   *
   * @readonly
   * @memberof XElement
   */
  public get localName() {
    return this.name;
  }

  /**
   * Gets attribute sequence
   *
   * @return {*}  {Iterable<XAttribute>}
   * @memberof XElement
   */
  public Attributes(): Iterable<XAttribute> {
    const result: Array<XAttribute> = [];
    for (const attName of Object.keys(this.attributes)) {
      result.push(new XAttribute(attName, this.attributes[attName]));
    }
    return result;
  }

  /**
   * Create XElement for DOM element
   *
   * @static
   * @param {Element} e
   * @return {*}
   * @memberof XElement
   */
  public static createFromDOMElement(e: Element) {
    const result = new XElement(e.localName);
    result.initWith(e.childNodes);
    for (const att of e.attributes) {
      result.attributes[att.name] = att.value;
    }
    return result;
  }

  /**
   * Convert this element to a string
   *
   * @return {*}  {string}
   * @memberof XElement
   */
  public toString(): string {
    return serializeXNodeToString(this);
  }

  /**
   * Remove current element from its parent
   *
   * @memberof XElement
   * @wMethod Remove
   */
  public remove() {
    if (this.parent) {
      this.parent.removeChildElement(this);
    }
  }

  /**
   *  Gets the value of the current node
   *
   * @readonly
   * @type {string}
   * @memberof XElement
   * @wProperty Value
   */
  get value(): string {
    const textNode = iuFirstOrDefault(iuOfType<XText>(this.contents, XText));
    return textNode?.value ?? null;
  }

  /**
   * Gets the value of the current node
   *
   * @memberof XElement
   * @wProperty Value
   */
  set value(newValue: string) {
    const textNode = iuFirstOrDefault(iuOfType<XText>(this.contents, XText));
    if (textNode) {
      textNode.value = newValue;
    } else {
      this.contents.push(new XText(newValue));
    }
  }
}

/**
 *  Gets elements from sequence
 *
 * @export
 * @param {Iterable<XElement>} sequence
 * @param {string} [name]
 * @return {*}  {Iterable<XElement>}
 */
export function* xElementsFromSequence(
  sequence: Iterable<XElement>,
  name?: string
): Iterable<XElement> {
  for (const e of sequence) {
    for (const innerElement of e.elements(name)) {
      yield innerElement;
    }
  }
}

/**
 *  Serialization XML step function
 *
 * @param {XNode} node
 * @param {XmlWriter} writer
 */
const serializingXNodeToString = (node: XNode, writer: XmlWriter) => {
  if (node instanceof XElement) {
    writer.WriteStartElement(node.localName);
    for (const att of node.Attributes()) {
      writer.WriteAttributeString(att.Name, att.Value);
    }
    for (const child of node.nodes()) {
      serializingXNodeToString(child, writer);
    }
    writer.WriteEndElement();
  } else if (node instanceof XText) {
    writer.WriteValue(node.value);
  }
};

/**
 *  Entry point for XML serialization
 *
 * @param {XNode} node
 * @return {*}
 */
const serializeXNodeToString = (node: XNode) => {
  const buffer = new StringWriter();
  const writer = XmlWriter.Create(buffer);
  serializingXNodeToString(node, writer);
  return buffer.toString();
};

/**
 * Removes all specified elements from its parent node
 *
 * @export
 * @template T
 * @param {Iterable<T>} sequence
 */
export function xRemoveElementsFromSequence<T extends XNode>(
  sequence: Iterable<T>
): void {
  for (const obj of sequence) {
    if (obj instanceof XElement) {
      obj.remove();
    }
  }
}

result-matching ""

    No results matching ""