HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux ip-172-31-4-197 6.8.0-1036-aws #38~22.04.1-Ubuntu SMP Fri Aug 22 15:44:33 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/api-storage/node_modules/fast-xml-parser/src/v5/OutputBuilders/JsArrBuilder.js
const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilder");

class OutputBuilder{
  constructor(options){
    this.options = buildOptions(options);
      this.registeredParsers = registerCommonValueParsers(this.options);
    }
    
    registerValueParser(name,parserInstance){//existing name will override the parser without warning
      this.registeredParsers[name] = parserInstance;
    }

  getInstance(parserOptions){
    return new JsArrBuilder(parserOptions, this.options, this.registeredParsers);
  }
}

const rootName = '!js_arr';
const BaseOutputBuilder = require("./BaseOutputBuilder");

class JsArrBuilder extends BaseOutputBuilder{

  constructor(parserOptions, options,registeredParsers) {
    super();
    this.tagsStack = [];
    this.parserOptions = parserOptions;
    this.options = options;
    this.registeredParsers = registeredParsers;

    this.root = new Node(rootName);
    this.currentNode = this.root;
    this.attributes = {};
  }

  addTag(tag){
    //when a new tag is added, it should be added as child of current node
    //TODO: shift this check to the parser
    if(tag.name === "__proto__") tag.name = "#__proto__";

    this.tagsStack.push(this.currentNode);
    this.currentNode = new Node(tag.name, this.attributes);
    this.attributes = {};
  }

  /**
   * Check if the node should be added by checking user's preference
   * @param {Node} node 
   * @returns boolean: true if the node should not be added
   */
  closeTag(){
    const node = this.currentNode;
    this.currentNode = this.tagsStack.pop(); //set parent node in scope
    if(this.options.onClose !== undefined){
      //TODO TagPathMatcher 
      const resultTag = this.options.onClose(node, 
        new TagPathMatcher(this.tagsStack,node));

      if(resultTag) return;
    }
    this.currentNode.child.push(node);  //to parent node
  }

  //Called by parent class methods
  _addChild(key, val){
    // if(key === "__proto__") tagName = "#__proto__";
    this.currentNode.child.push( {[key]: val });
    // this.currentNode.leafType = false;
  }

  /**
   * Add text value child node 
   * @param {string} text 
   */
  addValue(text){
    this.currentNode.child.push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
  }

  addPi(name){
    //TODO: set pi flag
    if(!this.options.ignorePiTags){
      const node = new Node(name, this.attributes);
      this.currentNode[":@"] = this.attributes;
      this.currentNode.child.push(node);
    }
    this.attributes = {};
  }
  getOutput(){
    return this.root.child[0];
  }
}



class Node{
  constructor(tagname, attributes){
    this.tagname = tagname;
    this.child = []; //nested tags, text, cdata, comments
    if(attributes && Object.keys(attributes).length > 0)
      this[":@"] = attributes;
  }
}

module.exports = OutputBuilder;