@ngx-i18nsupport/ngx-i18nsupport-lib
Version:
A Typescript library to work with Angular generated i18n files (xliff, xmb)
188 lines (175 loc) • 6.49 kB
text/typescript
import {DOMParser, XMLSerializer} from 'xmldom';
/**
* Created by martin on 01.05.2017.
* Some Tool functions for XML Handling.
*/
export class DOMUtilities {
/**
* return the first subelement with the given tag.
* @param element element
* @param tagName tagName
* @return subelement or null, if not existing.
*/
public static getFirstElementByTagName(element: Element | Document, tagName: string): Element {
const matchingElements = element.getElementsByTagName(tagName);
if (matchingElements && matchingElements.length > 0) {
return matchingElements.item(0);
} else {
return null;
}
}
/**
* return an element with the given tag and id attribute.
* @param element element
* @param tagName tagName
* @param id id
* @return subelement or null, if not existing.
*/
public static getElementByTagNameAndId(element: Element | Document, tagName: string, id: string): Element {
const matchingElements = element.getElementsByTagName(tagName);
if (matchingElements && matchingElements.length > 0) {
for (let i = 0; i < matchingElements.length; i++) {
const node: Element = matchingElements.item(i);
if (node.getAttribute('id') === id) {
return node;
}
}
}
return null;
}
/**
* Get next sibling, that is an element.
* @param element element
*/
public static getElementFollowingSibling(element: Element): Element {
if (!element) {
return null;
}
let e = element.nextSibling;
while (e) {
if (e.nodeType === e.ELEMENT_NODE) {
return <Element> e;
}
e = e.nextSibling;
}
return null;
}
/**
* Get previous sibling, that is an element.
* @param element element
*/
public static getElementPrecedingSibling(element: Element): Element {
if (!element) {
return null;
}
let e = element.previousSibling;
while (e) {
if (e.nodeType === e.ELEMENT_NODE) {
return <Element> e;
}
e = e.previousSibling;
}
return null;
}
/**
* return content of element as string, including all markup.
* @param element element
* @return content of element as string, including all markup.
*/
public static getXMLContent(element: Element): string {
if (!element) {
return null;
}
let result = new XMLSerializer().serializeToString(element);
const tagName = element.nodeName;
const reStartMsg: RegExp = new RegExp('<' + tagName + '[^>]*>', 'g');
result = result.replace(reStartMsg, '');
const reEndMsg: RegExp = new RegExp('</' + tagName + '>', 'g');
result = result.replace(reEndMsg, '');
return result;
}
/**
* return PCDATA content of element.
* @param element element
* @return PCDATA content of element.
*/
public static getPCDATA(element: Element): string {
if (!element) {
return null;
}
let result = '';
const childNodes = element.childNodes;
for (let i = 0; i < childNodes.length; i++) {
const child = childNodes.item(i);
if (child.nodeType === child.TEXT_NODE || child.nodeType === child.CDATA_SECTION_NODE) {
result = result + child.nodeValue;
}
}
return result.length === 0 ? null : result;
}
/**
* replace PCDATA content with a new one.
* @param element element
* @param pcdata pcdata
*/
public static replaceContentWithXMLContent(element: Element, pcdata: string) {
// remove all children
while (element.firstChild) {
element.removeChild(element.firstChild);
}
// parseICUMessage pcdata
const pcdataFragment: Document = new DOMParser().parseFromString('<fragment>' + pcdata + '</fragment>', 'application/xml');
const newChildren = pcdataFragment.getElementsByTagName('fragment').item(0).childNodes;
for (let j = 0; j < newChildren.length; j++) {
const newChild = newChildren.item(j);
element.appendChild(element.ownerDocument.importNode(newChild, true));
}
}
/**
* find the previous sibling that is an element.
* @param element element
* @return the previous sibling that is an element or null.
*/
public static getPreviousElementSibling(element: Node): Element {
let node = element.previousSibling;
while (node !== null) {
if (node.nodeType === node.ELEMENT_NODE) {
return <Element> node;
}
node = node.previousSibling;
}
return null;
}
/**
* Create an Element Node that is the next sibling of a given node.
* @param elementNameToCreate elementNameToCreate
* @param previousSibling previousSibling
* @return new element
*/
public static createFollowingSibling(elementNameToCreate: string, previousSibling: Node): Element {
const newElement = previousSibling.ownerDocument.createElement(elementNameToCreate);
return <Element> DOMUtilities.insertAfter(newElement, previousSibling);
}
/**
* Insert newElement directly after previousSibling.
* @param newElement newElement
* @param previousSibling previousSibling
*/
public static insertAfter(newElement: Node, previousSibling: Node): Node {
if (previousSibling.nextSibling !== null) {
previousSibling.parentNode.insertBefore(newElement, previousSibling.nextSibling);
} else {
previousSibling.parentNode.appendChild(newElement);
}
return newElement;
}
/**
* Insert newElement directly before nextSibling.
* @param newElement newElement
* @param nextSibling nextSibling
*/
public static insertBefore(newElement: Node, nextSibling: Node): Node {
nextSibling.parentNode.insertBefore(newElement, nextSibling);
return newElement;
}
}