import Writable from 'stream';
// Type definitions for xmlbuilder
// Project: https://github.com/oozcitak/xmlbuilder-js
//
// Original definitions (https://github.com/DefinitelyTyped/DefinitelyTyped) by:
//   Wallymathieu <https://github.com/wallymathieu>
//   GaikwadPratik <https://github.com/GaikwadPratik>

export = xmlbuilder;

declare namespace xmlbuilder {
    /**
     * Creates a new XML document and returns the root element node.
     * 
     * @param nameOrObject - name of the root element or a JS object to be 
     * converted to an XML tree
     * @param xmldecOrOptions - XML declaration or create options
     * @param doctypeOrOptions - Doctype declaration or create options
     * @param options - create options
     */
    function create(nameOrObject: string | { [name: string]: Object },
        xmldecOrOptions?: CreateOptions, doctypeOrOptions?: CreateOptions,
        options?: CreateOptions): XMLElement | XMLElement;

    interface CreateOptions {
        /** A version number string, e.g. 1.0 */
        version?: string;
        /** Encoding declaration, e.g. UTF-8 */
        encoding?: string;
        /** Standalone document declaration: true or false */
        standalone?: boolean;

        /** Public identifier of the DTD */
        pubID?: string;
        /** System identifier of the DTD */
        sysID?: string;

        /** Whether XML declaration and doctype will be included */
        headless?: boolean;
        /** Whether nodes with null values will be kept or ignored */
        keepNullNodes?: boolean;
        /** Whether attributes with null values will be kept or ignored */
        keepNullAttributes?: boolean;
        /** 
         * Whether decorator strings will be ignored when converting JS 
         * objects
         */
        ignoreDecorators?: boolean;
        /** 
         * Whether array items are created as separate nodes when passed 
         * as an object value
         */
        separateArrayItems?: boolean;
        /** Whether existing html entities are encoded */
        noDoubleEncoding?: boolean;
        /** Whether values will be validated and escaped or returned as is */
        noValidation?: boolean;
        /** A set of functions to use for converting values to strings */
        stringify?: XMLStringifier;
        /** 
         * The default XML writer to use for converting nodes to string. 
         * If the default writer is not set, the built-in XMLStringWriter 
         * will be used instead. 
         */
        writer?: XMLWriter;
    }

    interface XMLStringifier {
        /** Converts an element or attribute name to string */
        name?: (v: any) => string;
        /** Converts the contents of a text node to string */
        text?: (v: any) => string;
        /** Converts the contents of a CDATA node to string */
        cdata?: (v: any) => string;
        /** Converts the contents of a comment node to string */
        comment?: (v: any) => string;
        /** Converts the contents of a raw text node to string */
        raw?: (v: any) => string;
        /** Converts attribute value to string */
        attValue?: (v: any) => string;
        /** Converts processing instruction target to string */
        insTarget?: (v: any) => string;
        /** Converts processing instruction value to string */
        insValue?: (v: any) => string;
        /** Converts XML version to string */
        xmlVersion?: (v: any) => string;
        /** Converts XML encoding to string */
        xmlEncoding?: (v: any) => string;
        /** Converts standalone document declaration to string */
        xmlStandalone?: (v: any) => string;
        /** Converts Doctype public identifier to string */
        dtdPubID?: (v: any) => string;
        /** Converts Doctype system identifier to string */
        dtdSysID?: (v: any) => string;
        /** Converts !ELEMENT node content inside Doctype to string */
        dtdElementValue?: (v: any) => string;
        /** Converts !ATTLIST node type inside Doctype to string */
        dtdAttType?: (v: any) => string;
        /** Converts !ATTLIST node default value inside Doctype to string */
        dtdAttDefault?: (v: any) => string;
        /** Converts !ENTITY node content inside Doctype to string */
        dtdEntityValue?: (v: any) => string;
        /** Converts !NOTATION node content inside Doctype to string */
        dtdNData?: (v: any) => string;

        /** 
         * When prepended to a JS object key, converts the key-value pair 
         * to an attribute. 
         */
        convertAttKey?: string;
        /** 
         * When prepended to a JS object key, converts the key-value pair 
         * to a processing instruction node. 
         */
        convertPIKey?: string;
        /** 
         * When prepended to a JS object key, converts its value to a text node. 
         * 
         * _Note:_ Since JS objects cannot contain duplicate keys, multiple text nodes 
         * can be created by adding some unique text after each object key. 
         * For example: `{ '#text1': 'some text', '#text2': 'more text' };`
         */
        convertTextKey?: string;
        /** 
         * When prepended to a JS object key, converts its value to a CDATA 
         * node. 
         */
        convertCDataKey?: string;
        /** 
         * When prepended to a JS object key, converts its value to a 
         * comment node.
         */
        convertCommentKey?: string;
        /** 
         * When prepended to a JS object key, converts its value to a raw 
         * text node. 
         */
        convertRawKey?: string;

        /** Escapes special characters in text */
        textEscape?: (v: string) => string;

        /** Escapes special characters in attribute values */
        attEscape?: (v: string) => string;
    }

    interface XMLWriter {
        /** 
         * Writes the indentation string for the given level. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        indent?: (node: XMLNode, options: WriterOptions, level: number) => any

        /** 
         * Writes the newline string. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        endline?: (node: XMLNode, options: WriterOptions, level: number) => any

        /** 
         * Writes an attribute. 
         * 
         * @param att - current attribute
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        attribute?: (att: XMLAttribute, options: WriterOptions, level: number) => any

        /** 
         * Writes a CDATA node.
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        cdata?: (node: XMLCData, options: WriterOptions, level: number) => any

        /** 
         * Writes a comment node. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        comment?: (node: XMLComment, options: WriterOptions, level: number) => any

        /** 
         * Writes the XML declaration (e.g. `<?xml version="1.0"?>`). 
         * 
         * @param node - XML declaration node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        declaration?: (node: XMLDeclaration, options: WriterOptions, level: number) => any

        /** 
         * Writes the DocType node and its children. 
         * 
         * _Note:_ Be careful when overriding this function as this function
         * is also responsible for writing the internal subset of the DTD. 
         * 
         * @param node - DOCTYPE node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        docType?: (node: XMLDocType, options: WriterOptions, level: number) => any

        /** 
         * Writes an element node. 
         * 
         * _Note:_ Be careful when overriding this function as this function
         * is also responsible for writing the element attributes and child 
         * nodes.
         * 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        element?: (node: XMLElement, options: WriterOptions, level: number) => any

        /** 
         * Writes a processing instruction node. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        processingInstruction?: (node: XMLProcessingInstruction, options: WriterOptions, level: number) => any

        /** 
         * Writes a raw text node. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        raw?: (node: XMLRaw, options: WriterOptions, level: number) => any

        /** 
         * Writes a text node. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        text?: (node: XMLText, options: WriterOptions, level: number) => any

        /** 
         * Writes an attribute node (!ATTLIST) inside the DTD. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        dtdAttList?: (node: XMLDTDAttList, options: WriterOptions, level: number) => any

        /** 
         * Writes an element node (!ELEMENT) inside the DTD. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        dtdElement?: (node: XMLDTDElement, options: WriterOptions, level: number) => any

        /** 
         * Writes an entity node (!ENTITY) inside the DTD. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        dtdEntity?: (node: XMLDTDEntity, options: WriterOptions, level: number) => any

        /** 
         * Writes a notation node (!NOTATION) inside the DTD. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        dtdNotation?: (node: XMLDTDNotation, options: WriterOptions, level: number) => any

        /** 
         * Called right after starting writing a node. This function doesn't 
         * produce any output, but can be used to alter the state of the writer. 
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        openNode?: (node: XMLNode, options: WriterOptions, level: number) => void

        /** 
         * Called right before completing writing a node. This function doesn't 
         * produce any output, but can be used to alter the state of the writer.
         * 
         * @param node - current node
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        closeNode?: (node: XMLNode, options: WriterOptions, level: number) => void

        /** 
         * Called right after starting writing an attribute. This function doesn't 
         * produce any output, but can be used to alter the state of the writer. 
         * 
         * @param node - current attribute
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        openAttribute?: (att: XMLAttribute, options: WriterOptions, level: number) => void

        /** 
         * Called right before completing writing an attribute. This function 
         * doesn't produce any output, but can be used to alter the state of 
         * the writer. 
         * 
         * @param node - current attribute
         * @param options - writer options and state information
         * @param level - current depth of the XML tree
         */
        closeAttribute?: (att: XMLAttribute, options: WriterOptions, level: number) => void
    }

    interface WriterOptions {
        /** Pretty print the XML tree */
        pretty?: boolean;
        /** Indentation string for pretty printing */
        indent?: string;
        /** Newline string for pretty printing */
        newline?: string;
        /** A fixed number of indents to offset strings */
        offset?: number;
        /** Maximum column width */
        width?: number;
        /** Whether to output closing tags for empty element nodes */
        allowEmpty?: boolean;
        /** Whether to pretty print text nodes */
        dontPrettyTextNodes?: boolean;
        /** A string to insert before closing slash character */
        spaceBeforeSlash?: string | boolean;
        /** User state object that is saved between writer functions */
        user?: any;
        /** The current state of the writer */
        state?: WriterState;
        /** Writer function overrides */
        writer?: XMLWriter;
    }

    enum WriterState {
        /** Writer state is unknown */
        None = 0,
        /** Writer is at an opening tag, e.g. <node> */
        OpenTag = 1,
        /** Writer is inside an element */
        InsideTag = 2,
        /** Writer is at a closing tag, e.g. </node> */
        CloseTag = 3
    }

    /**
     * Creates a new XML document and returns the document node.
     * This function creates an empty document without the XML prolog or
     * a root element.
     * 
     * @param options - create options
     */
    function begin(options?: BeginOptions): XMLDocument;

    interface BeginOptions {
        /** Whether nodes with null values will be kept or ignored */
        keepNullNodes?: boolean;
        /** Whether attributes with null values will be kept or ignored */
        keepNullAttributes?: boolean;
        /** 
         * Whether decorator strings will be ignored when converting JS 
         * objects
         */
        ignoreDecorators?: boolean;
        /** 
         * Whether array items are created as separate nodes when passed 
         * as an object value
         */
        separateArrayItems?: boolean;
        /** Whether existing html entities are encoded */
        noDoubleEncoding?: boolean;
        /** Whether values will be validated and escaped or returned as is */
        noValidation?: boolean;
        /** A set of functions to use for converting values to strings */
        stringify?: XMLStringifier;
        /** 
         * The default XML writer to use for converting nodes to string. 
         * If the default writer is not set, the built-in XMLStringWriter 
         * will be used instead. 
         */
        writer?: XMLWriter | WriterOptions;
    }

    type OnDataCallback = (chunk: string, level: number) => void;
    type OnEndCallback = () => void;

    /**
     * Creates a new XML document in callback mode and returns the document
     * node.
     * 
     * @param options - create options
     * @param onData - the function to be called when a new chunk of XML is
     * output. The string containing the XML chunk is passed to `onData` as
     * its first argument and the current depth of the tree is passed as its
     * second argument.
     * @param onEnd - the function to be called when the XML document is 
     * completed with `end`. `onEnd` does not receive any arguments.
     */
    function begin(options?: BeginOptions | OnDataCallback,
        onData?: OnDataCallback | OnEndCallback,
        onEnd?: OnEndCallback): XMLDocumentCB;

    /**
     * Creates and returns a default string writer.
     * 
     * @param options - writer options
     */
    function stringWriter(options?: WriterOptions): XMLWriter

    /**
     * Creates and returns a default stream writer.
     * 
     * @param stream - a writeable stream
     * @param options - writer options
     */
    function streamWriter(stream: Writable, options?: WriterOptions): XMLWriter

    enum NodeType {
        /** An element node */
        Element = 1,
        /** An attribute node */
        Attribute = 2,
        /** A text node */
        Text = 3,
        /** A CDATA node */
        CData = 4,
        /** An entity reference node inside Doctype */
        EntityReference = 5,
        /** An entity declaration node inside Doctype */
        EntityDeclaration = 6,
        /** A processing instruction node */
        ProcessingInstruction = 7,
        /** A comment node */
        Comment = 8,
        /** A document node */
        Document = 9,
        /** A Doctype node */
        DocType = 10,
        /** A document fragment node */
        DocumentFragment = 11,
        /** A notation declaration node inside Doctype */
        NotationDeclaration = 12,
        /** An XML declaration node */
        Declaration = 201,
        /** A raw text node */
        Raw = 202,
        /** An attribute declaraiton node inside Doctype */
        AttributeDeclaration = 203,
        /** An element declaration node inside Doctype */
        ElementDeclaration = 204
    }

    export import nodeType = NodeType;
    export import writerState = WriterState;

    interface XMLToStringOptions {
        /** Pretty print the XML tree */
        pretty?: boolean;
        /** Indentation string for pretty printing */
        indent?: string;
        /** Newline string for pretty printing */
        newline?: string;
        /** A fixed number of indents to offset strings */
        offset?: number;
        /** Maximum column width */
        width?: number;
        /** Whether to output closing tags for empty element nodes */
        allowEmpty?: boolean;
        /** Whether to pretty print text nodes */
        dontPrettyTextNodes?: boolean;
        /** A string to insert before closing slash character */
        spaceBeforeSlash?: string | boolean;
        /** 
         * The default XML writer to use for converting nodes to string. 
         * If the default writer is not set, the built-in XMLStringWriter 
         * will be used instead. 
         */
        writer?: XMLWriter;
    }

    /**
     * Represents the XML document.
     */
    class XMLDocument extends XMLNode {
        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents an XML attribute.
     */
    class XMLAttribute {
        /** 
         * Type of the node 
         */
        type: NodeType;
        /** 
         * Parent element node 
         */
        parent: XMLElement;
        /** 
         * Attribute name 
         */
        name: string;
        /** 
         * Attribute value 
         */
        value: string;

        /** 
         * Creates a clone of this node 
         */
        clone(): XMLAttribute;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents the base class of XML nodes.
     */
    abstract class XMLNode {
        /** 
         * Type of the node 
         */
        type: NodeType;
        /** 
         * Parent element node 
         */
        parent: XMLElement;
        /** 
         * Child nodes 
         */
        children: XMLNode[]

        /**
         * Creates a new child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `ele` and `e`
         * 
         * @param name - element node name or a JS object defining the nodes to insert
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the last top level node created
         */
        element(name: any, attributes?: Object, text?: any): XMLElement;
        ele(name: any, attributes?: Object, text?: any): XMLElement;
        e(name: any, attributes?: Object, text?: any): XMLElement;

        /**
         * Adds or modifies an attribute.
         * 
         * _Aliases:_ `att`, `a`
         * 
         * @param name - attribute name
         * @param value - attribute value
         * 
         * @returns the parent element node
         */
        attribute(name: any, value?: any): XMLElement;
        att(name: any, value?: any): XMLElement;
        a(name: any, value?: any): XMLElement;

        /**
         * Creates a new sibling node and inserts it before this node.
         * 
         * @param name - element node name or a JS object defining the nodes to insert
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the new node
         */
        insertBefore(name: any, attributes?: Object, text?: any): XMLElement;
        /**
         * Creates a new sibling node and inserts it after this node.
         * 
         * @param name - element node name or a JS object defining the nodes to insert
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the new node
         */
        insertAfter(name: any, attributes?: Object, text?: any): XMLElement;
        /**
         * Removes this node from the tree.
         * 
         * @returns the parent node
         */
        remove(): XMLElement;

        /**
         * Creates a new child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `nod` and `n`
         * 
         * @param name - element node name
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the node created
         */
        node(name: string, attributes?: Object, text?: any): XMLElement;
        nod(name: string, attributes?: Object, text?: any): XMLElement;
        n(name: string, attributes?: Object, text?: any): XMLElement;

        /**
         * Creates a new text child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `txt` and `t`
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        text(value: string): XMLElement;
        txt(value: string): XMLElement;
        t(value: string): XMLElement;

        /**
         * Creates a new CDATA child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `dat` and `d`
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        cdata(value: string): XMLElement;
        dat(value: string): XMLElement;
        d(value: string): XMLElement;

        /**
         * Creates a new comment child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `com` and `c`
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        comment(value: string): XMLElement;
        com(value: string): XMLElement;
        c(value: string): XMLElement;

        /**
         * Creates a comment node before the current node
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        commentBefore(value: string): XMLElement;

        /**
         * Creates a comment node after the current node
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        commentAfter(value: string): XMLElement;

        /**
         * Creates a new raw text child node and appends it to the list of child nodes.
         * 
         * _Alias:_ `r`
         * 
         * @param value - node value
         * 
         * @returns the parent node
         */
        raw(value: string): XMLElement;
        r(value: string): XMLElement;

        /**
         * Creates a new processing instruction node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `ins` and `i`
         * 
         * @param target - node target
         * @param value - node value
         * 
         * @returns the parent node
         */
        instruction(target: string, value: any): XMLElement;
        instruction(array: Array<any>): XMLElement;
        instruction(obj: Object): XMLElement;
        ins(target: string, value: any): XMLElement;
        ins(array: Array<any>): XMLElement;
        ins(obj: Object): XMLElement;
        i(target: string, value: any): XMLElement;
        i(array: Array<any>): XMLElement;
        i(obj: Object): XMLElement;

        /**
         * Creates a processing instruction node before the current node.
         * 
         * @param target - node target
         * @param value - node value
         * 
         * @returns the parent node
         */        
        instructionBefore(target: string, value: any): XMLElement;
      
        /**
         * Creates a processing instruction node after the current node.
         * 
         * @param target - node target
         * @param value - node value
         * 
         * @returns the parent node
         */        
        instructionAfter(target: string, value: any): XMLElement;

        /**
         * Creates the XML declaration.
         * 
         * _Alias:_ `dec`
         * 
         * @param version - version number string, e.g. `1.0`
         * @param encoding - encoding declaration, e.g. `UTF-8`
         * @param standalone - standalone document declaration: `true` or `false`
         * 
         * @returns the root element node
         */
        declaration(version?: string | { version?: string, encoding?: string, standalone?: boolean }, encoding?: string, standalone?: boolean): XMLElement;
        dec(version?: string | { version?: string, encoding?: string, standalone?: boolean }, encoding?: string, standalone?: boolean): XMLElement;

        /**
         * Creates the document type definition.
         * 
         * _Alias:_ `dtd`
         * 
         * @param pubID - public identifier of the DTD
         * @param sysID - system identifier of the DTD
         * 
         * @returns the DOCTYPE node
         */
        doctype(pubID?: string | { pubID?: string, sysID?: string }, sysID?: string): XMLDocType;
        dtd(pubID?: string | { pubID?: string, sysID?: string }, sysID?: string): XMLDocType;

        /**
         * Takes the root node of the given XML document and appends it 
         * to child nodes.
         * 
         * @param doc - the document whose root node to import
         * 
         * @returns the current node
         */
        importDocument(doc: XMLNode): XMLElement;

        /**
         * Converts the XML document to string.
         * 
         * @param options - conversion options
         */
        end(options?: XMLWriter | XMLToStringOptions): string;

        /**
         * Returns the previous sibling node.
         */
        prev(): XMLNode;
        /**
         * Returns the next sibling node.
         */
        next(): XMLNode;
        /**
         * Returns the parent node.
         * 
         * _Alias:_ `u`
         */
        up(): XMLElement;
        u(): XMLElement;
        /**
         * Returns the document node.
         * 
         * _Alias:_ `doc`
         */
        document(): XMLDocument;
        doc(): XMLDocument;

        /**
         * Returns the root element node.
         */
        root(): XMLElement;
    }

    /**
     * Represents the base class of character data nodes.
     */
    abstract class XMLCharacterData extends XMLNode {
        /** Node value */
        value: string;
    }

    /**
     * Represents a CDATA node.
     */
    class XMLCData extends CharacterData {
        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** Creates a clone of this node */
        clone(): XMLCData;
    }

    /**
     * Represents a comment node.
     */
    class XMLComment extends CharacterData {
        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** Creates a clone of this node */
        clone(): XMLComment;
    }

    /**
     * Represents a processing instruction node.
     */
    class XMLProcessingInstruction extends CharacterData {
        /**  Instruction target */
        target: string;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** Creates a clone of this node */
        clone(): XMLProcessingInstruction;
    }

    /**
     * Represents a raw text node.
     */
    class XMLRaw extends CharacterData {
        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** Creates a clone of this node */
        clone(): XMLRaw;
    }

    /**
     * Represents a text node.
     */
    class XMLText extends CharacterData {
        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** Creates a clone of this node */
        clone(): XMLText;
    }

    /**
     * Represents the XML declaration.
     */
    class XMLDeclaration {
        /** A version number string, e.g. 1.0 */
        version: string;
        /** Encoding declaration, e.g. UTF-8 */
        encoding: string;
        /** Standalone document declaration: true or false */
        standalone: boolean;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents the document type definition.
     */
    class XMLDocType extends XMLNode {
        /** Public identifier of the DTD */
        pubID: string;
        /** System identifier of the DTD */
        sysID: string;

        /**
         * Creates an element type declaration.
         * 
         * _Alias:_ `ele`
         * 
         * @param name - element name
         * @param value - element content (defaults to `#PCDATA`)
         * 
         * @returns the DOCTYPE node
         */
        element(name: string, value?: Object): XMLDocType;
        ele(name: string, value?: Object): XMLDocType;

        /**
         * Creates an attribute declaration
         * 
         * _Alias:_ `att`
         * 
         * @param elementName - the name of the element containing this attribute
         * @param attributeName - attribute name
         * @param attributeType - type of the attribute (defaults to `CDATA`)
         * @param defaultValueType - default value type (either `#REQUIRED`,
         * `#IMPLIED`, `#FIXED` or `#DEFAULT`) (defaults to `#IMPLIED`)
         * @param defaultValue - default value of the attribute (only used
         * for `#FIXED` or `#DEFAULT`)
         * 
         * @returns the DOCTYPE node
         */
        attList(elementName: string, attributeName: string, attributeType: string, defaultValueType?: string, defaultValue?: any): XMLDocType;
        att(elementName: string, attributeName: string, attributeType: string, defaultValueType?: string, defaultValue?: any): XMLDocType;

        /**
         * Creates a general entity declaration
         * 
         * _Alias:_ `ent`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the DOCTYPE node
         */
        entity(name: string, value: string | { pubID?: string, sysID?: string, nData?: string }): XMLDocType;
        ent(name: string, value: string | { pubID?: string, sysID?: string, nData?: string }): XMLDocType;

        /**
         * Creates a parameter entity declaration
         * 
         * _Alias:_ `pent`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the DOCTYPE node
         */
        pEntity(name: string, value: string | { pubID?: string, sysID?: string }): XMLDocType;
        pent(name: string, value: string | { pubID?: string, sysID?: string }): XMLDocType;

        /**
         * Creates a notation declaration
         * 
         * _Alias:_ `not`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the DOCTYPE node
         */
        notation(name: string, value: { pubID?: string, sysID?: string }): XMLDocType;
        not(name: string, value: { pubID?: string, sysID?: string }): XMLDocType;

        /**
         * Creates a new CDATA child node and appends it to the list of child nodes.
         * 
         * _Alias:_ `dat`
         * 
         * @param value - node value
         * 
         * @returns the DOCTYPE node
         */
        cdata(value: string): XMLDocType;
        dat(value: string): XMLDocType;

        /**
         * Creates a new comment child node and appends it to the list of child nodes.
         * 
         * _Alias:_ `com`
         * 
         * @param value - node value
         * 
         * @returns the DOCTYPE node
         */
        comment(value: string): XMLDocType;
        com(value: string): XMLDocType;

        /**
         * Creates a new processing instruction node and appends it to the list of child nodes.
         * 
         * _Alias:_ `ins`
         * 
         * @param target - node target
         * @param value - node value
         * 
         * @returns the DOCTYPE node
         */
        instruction(target: string, value: any): XMLDocType;
        instruction(array: Array<any>): XMLDocType;
        instruction(obj: Object): XMLDocType;
        ins(target: string, value: any): XMLDocType;
        ins(array: Array<any>): XMLDocType;
        ins(obj: Object): XMLDocType;
      
        /**
         * Returns the root element node.
         * 
         * _Alias:_ `up`
         */
        root(): XMLElement;
        up(): XMLElement;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;

        /** 
         * Creates a clone of this node 
         */
        clone(): XMLDocType;
    }

    /**
     * Represents an attribute list in the DTD.
     */
    class XMLDTDAttList {
        /** The name of the element containing this attribute */
        elementName: string;
        /** Attribute name */
        attributeName: string;
        /** Type of the attribute */
        attributeType: string;
        /** 
         * Default value type (either `#REQUIRED`, `#IMPLIED`, `#FIXED` 
         * or `#DEFAULT`)
         */
        defaultValueType: string;
        /** 
         * Default value of the attribute (only used for `#FIXED` or 
         * `#DEFAULT`)
         */
        defaultValue: string;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents an element in the DTD.
     */
    class XMLDTDElement {
        /** The name of the element */
        name: string;
        /** Element content*/
        value: string;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents an entity in the DTD.
     */
    class XMLDTDEntity {
        /** 
         * Determines whether this is a parameter entity (`true`) or a 
         * general entity (`false`).
         */
        pe: boolean;
        /** The name of the entity */
        name: string;
        /** Public identifier */
        pubID: string;
        /** System identifier */
        sysID: string;
        /** Notation declaration */
        nData: string;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents a notation in the DTD.
     */
    class XMLDTDNotation {
        /** The name of the notation */
        name: string;
        /** Public identifier */
        pubID: string;
        /** System identifier */
        sysID: string;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents an element node.
     */
    class XMLElement extends XMLNode {
        /** Element node name */
        name: string;
        /** Element attributes */
        attribs: { string: XMLAttribute };

        /** 
         * Creates a clone of this node 
         */
        clone(): XMLElement;

        /**
         * Adds or modifies an attribute.
         * 
         * _Aliases:_ `att`, `a`
         * 
         * @param name - attribute name
         * @param value - attribute value
         * 
         * @returns the parent element node
         */
        attribute(name: any, value?: any): XMLElement;
        att(name: any, value?: any): XMLElement;
        a(name: any, value?: any): XMLElement;

        /**
         * Removes an attribute.
         * 
         * @param name - attribute name
         * 
         * @returns the parent element node
         */
        removeAttribute(name: string | string[]): XMLElement;

        /** 
         * Converts the node to string 
         * 
         * @param options - conversion options
         */
        toString(options?: XMLToStringOptions): string;
    }

    /**
     * Represents an XML document builder used in callback mode with the
     * `begin` function.
     */
    class XMLDocumentCB {

        /**
         * Creates a new child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `nod` and `n`
         * 
         * @param name - element node name
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the document builder object
         */
        node(name: string, attributes?: Object, text?: any): XMLDocumentCB;
        nod(name: string, attributes?: Object, text?: any): XMLDocumentCB;
        n(name: string, attributes?: Object, text?: any): XMLDocumentCB;

        /**
         * Creates a child element node
         * 
         * _Aliases:_ `ele` and `e`
         * 
         * @param name - element node name or a JS object defining the nodes to insert
         * @param attributes - node attributes
         * @param text - node text
         * 
         * @returns the document builder object
         */
        element(name: any, attributes?: Object, text?: any): XMLDocumentCB;
        ele(name: any, attributes?: Object, text?: any): XMLDocumentCB;
        e(name: any, attributes?: Object, text?: any): XMLDocumentCB;

        /**
         * Adds or modifies an attribute.
         * 
         * _Aliases:_ `att` and `a`
         * 
         * @param name - attribute name
         * @param value - attribute value
         * 
         * @returns the document builder object
         */
        attribute(name: any, value?: any): XMLDocumentCB;
        att(name: any, value?: any): XMLDocumentCB;
        a(name: any, value?: any): XMLDocumentCB;

        /**
         * Creates a new text child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `txt` and `t`
         * 
         * @param value - node value
         * 
         * @returns the document builder object
         */
        text(value: string): XMLDocumentCB;
        txt(value: string): XMLDocumentCB;
        t(value: string): XMLDocumentCB;

        /**
         * Creates a new CDATA child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `dat` and `d`
         * 
         * @param value - node value
         * 
         * @returns the document builder object
         */
        cdata(value: string): XMLDocumentCB;
        dat(value: string): XMLDocumentCB;
        d(value: string): XMLDocumentCB;

        /**
         * Creates a new comment child node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `com` and `c`
         * 
         * @param value - node value
         * 
         * @returns the document builder object
         */
        comment(value: string): XMLDocumentCB;
        com(value: string): XMLDocumentCB;
        c(value: string): XMLDocumentCB;

        /**
         * Creates a new raw text child node and appends it to the list of child nodes.
         * 
         * _Alias:_ `r`
         * 
         * @param value - node value
         * 
         * @returns the document builder object
         */
        raw(value: string): XMLDocumentCB;
        r(value: string): XMLDocumentCB;

        /**
         * Creates a new processing instruction node and appends it to the list of child nodes.
         * 
         * _Aliases:_ `ins` and `i`
         * 
         * @param target - node target
         * @param value - node value
         * 
         * @returns the document builder object
         */
        instruction(target: string, value: any): XMLDocumentCB;
        instruction(array: Array<any>): XMLDocumentCB;
        instruction(obj: Object): XMLDocumentCB;
        ins(target: string, value: any): XMLDocumentCB;
        ins(array: Array<any>): XMLDocumentCB;
        ins(obj: Object): XMLDocumentCB;
        i(target: string, value: any): XMLDocumentCB;
        i(array: Array<any>): XMLDocumentCB;
        i(obj: Object): XMLDocumentCB;

        /**
         * Creates the XML declaration.
         * 
         * _Alias:_ `dec`
         * 
         * @param version - version number string, e.g. `1.0`
         * @param encoding - encoding declaration, e.g. `UTF-8`
         * @param standalone - standalone document declaration: `true` or `false`
         * 
         * @returns the document builder object
         */
        declaration(version?: string, encoding?: string, standalone?: boolean): XMLDocumentCB;
        dec(version?: string, encoding?: string, standalone?: boolean): XMLDocumentCB;

        /**
         * Creates the document type definition.
         * 
         * _Alias:_ `dtd`
         * 
         * @param root - the name of the root node
         * @param pubID - public identifier of the DTD
         * @param sysID - system identifier of the DTD
         * 
         * @returns the document builder object
         */
        doctype(root: string, pubID?: string, sysID?: string): XMLDocumentCB;
        dtd(root: string, pubID?: string, sysID?: string): XMLDocumentCB;

        /**
         * Creates an element type declaration.
         * 
         * _Aliases:_ `element` and `ele`
         * 
         * @param name - element name
         * @param value - element content (defaults to `#PCDATA`)
         * 
         * @returns the document builder object
         */
        dtdElement(name: string, value?: Object): XMLDocumentCB;
        element(name: string, value?: Object): XMLDocumentCB;
        ele(name: string, value?: Object): XMLDocumentCB;

        /**
         * Creates an attribute declaration
         * 
         * _Alias:_ `att`
         * 
         * @param elementName - the name of the element containing this attribute
         * @param attributeName - attribute name
         * @param attributeType - type of the attribute (defaults to `CDATA`)
         * @param defaultValueType - default value type (either `#REQUIRED`,
         * `#IMPLIED`, `#FIXED` or `#DEFAULT`) (defaults to `#IMPLIED`)
         * @param defaultValue - default value of the attribute (only used
         * for `#FIXED` or `#DEFAULT`)
         * 
         * @returns the document builder object
         */
        attList(elementName: string, attributeName: string, attributeType: string, defaultValueType?: string, defaultValue?: any): XMLDocumentCB;
        att(elementName: string, attributeName: string, attributeType: string, defaultValueType?: string, defaultValue?: any): XMLDocumentCB;
        a(elementName: string, attributeName: string, attributeType: string, defaultValueType?: string, defaultValue?: any): XMLDocumentCB;

        /**
         * Creates a general entity declaration
         * 
         * _Alias:_ `ent`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the document builder object
         */
        entity(name: string, value: string | { pubID?: string, sysID?: string, nData?: string }): XMLDocumentCB;
        ent(name: string, value: string | { pubID?: string, sysID?: string, nData?: string }): XMLDocumentCB;

        /**
         * Creates a parameter entity declaration
         * 
         * _Alias:_ `pent`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the document builder object
         */
        pEntity(name: string, value: string | { pubID?: string, sysID?: string }): XMLDocumentCB;
        pent(name: string, value: string | { pubID?: string, sysID?: string }): XMLDocumentCB;

        /**
         * Creates a notation declaration
         * 
         * _Alias:_ `not`
         * 
         * @param name - the name of the entity
         * @param value - entity parameters
         * 
         * @returns the document builder object
         */
        notation(name: string, value: { pubID?: string, sysID?: string }): XMLDocumentCB;
        not(name: string, value: { pubID?: string, sysID?: string }): XMLDocumentCB;

        /**
         * Ends the document.
         */
        end(): void;

        /**
         * Moves up to the parent node.
         * 
         * _Alias:_ `u`
         */
        up(): XMLDocumentCB;
        u(): XMLDocumentCB;
    }

}
