javascriptnode.jsxml-builder

Passing a variable or property value to a method in a JavaScript object returns "undefined"


I'm trying to build an xml file from 2 JSON objects through 2 cascading loops. In the second loop, I can't find how to pass a value from the previous loop:

In the example below, I would like to pass the "docnumber" value to my second loop (through GroupsACLJSON) in order to build the "acl" node from the second JSON object, but using "this.docnumber" from the parent object property returns "undefined", thus leading to an empty "acl" node.

var documentsJSON = [{
    "folder": "Enterprise1",
    "extension": "DOCX",
    "docnumber": "3912271",
    "version": "1"
  },
  {
    "folder": "Enterprise2",
    "extension": "MSG",
    "docnumber": "3912298",
    "version": "1"
  },
  {
    "folder": "Enterprise3",
    "extension": "DOCX",
    "docnumber": "3912692",
    "version": "1"
  }
]

var GroupsACLJSON = [{
    "docNumber": "3912271",
    "groupName": "group1"
  },
  {
    "docNumber": "3912271",
    "groupName": "group2"
  },
  {
    "docNumber": "3912298",
    "groupName": "group3"
  },
  {
    "docNumber": "3912298",
    "groupName": "group4"
  }
]

// importing and declaring xmlbuilder variable: 
var builder = require('xmlbuilder');
var xmlObjectImporter = builder.create('import', {
  version: '1.0',
  encoding: 'UTF-8',
  standalone: true
}, {
  headless: false,
  stringify: {}
});

var nodeArray = [];
var xmlObjectElement = {
  node: function() {
    for (var i = 0; i < documentsJSON.length; i++) {
      // populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
      var nodeObject = {
        location: documentsJSON[i].folder,
        category: {
          attribute: [{
            '#text': documentsJSON[i].docnumber,
            '@name': "Document Number"
          }],
          '@name': "ACME",
        },
        docnumber: documentsJSON[i].docnumber,
        // loop through GroupsACLJSON to find if we have specific ACL groups for this document:
        acl: function() {
          var documentNumber = this.docnumber
          console.log(this.docnumber);
          var acl = [];
          var aclObject = {};
          for (var j = 0; j < GroupsACLJSON.length; j++) {
            if (GroupsACLJSON[j].docNumber == documentNumber) {
              aclObject = {
                '@group': GroupsACLJSON[j].groupName,
                '@permissions': '111111100'
              };
              acl.push(aclObject);
            };
          };
          return acl;
        },
        '@type': "document",
        '@action': "create",
      };
      nodeArray.push(nodeObject);
    };
    return nodeArray;
  }
};

// writing our elements in the xml file using the XML object:
var ele = xmlObjectImporter.ele(xmlObjectElement);

console.log(xmlObjectImporter.toString({
  pretty: true
}));

Here is an output I would expect from this:

<import>
  <node type="document" action="create">
    <location>Enterprise1</location>
    <category name="ACME">
      <attribute name="Document Number">3912271</attribute>
    </category>
    <docnumber>3912271</docnumber>
    <acl group="group1" permissions="111111100" />
    <acl group="group2" permissions="111111100" />
  </node>
  <node type="document" action="create">
    <location>Enterprise2</location>
    <category name="ACME">
      <attribute name="Document Number">3912298</attribute>
    </category>
    <docnumber>3912298</docnumber>
    <acl group="group3" permissions="111111100" />
    <acl group="group4" permissions="111111100" />
  </node>
  <node type="document" action="create">
    <location>Enterprise3</location>
    <category name="ACME">
      <attribute name="Document Number">3912692</attribute>
    </category>
    <docnumber>3912692</docnumber>
    <acl/>
  </node>
</import>

Solution

  • Following nxSolari's suggestion, I re-wrote the code using 2 functions instead of a big object and methods and got the desired result. I still don't understand how the code gets through the objects and methods, but here is the new working code:

        'use strict';
    
        var documentsJSON = [{
            "folder":"Enterprise1" , 
            "extension":"DOCX" , 
            "docnumber":"3912271" , 
            "version":"1"
            },
            {
            "folder":"Enterprise2" , 
            "extension":"MSG" , 
            "docnumber":"3912298" , 
            "version":"1"
            },
            {
            "folder":"Enterprise3" , 
            "extension":"DOCX" , 
            "docnumber":"3912692" , 
            "version":"1"
            }
        ]
    
        var GroupsACLJSON = [{
            "docNumber":"3912271" , 
            "groupName":"group1"
            },
            {
            "docNumber":"3912271" , 
            "groupName":"group2"
            },
            {
            "docNumber":"3912298" , 
            "groupName":"group3"
            },
            {
            "docNumber":"3912298" , 
            "groupName":"group4"
            },
            {
            "docNumber":"3912692" , 
            "groupName":"group5"
            }
        ]
    
    
        // importing and declaring xmlbuilder variable: 
        var builder = require('xmlbuilder');
        var xmlObjectImporter = builder.create('import', {
            version: '1.0', 
            encoding: 'UTF-8', 
            standalone: true
        }, {
            headless: false, 
            stringify: {}
        });
    
        var xmlObjectElement = {};
    
        function buildACLnode(passedDoc, acls) {
            var acl= [];
            for (var jDoc = 0 ; jDoc < acls.length ; jDoc++) {
                if (acls[jDoc].docNumber == passedDoc) {
                    var aclObject = {
                        '@group':  acls[jDoc].groupName,
                        '@permissions': '111111100'
                    };
                    acl.push(aclObject);
                };
            };
            return acl;
        }
    
        function buildXML(documents) {
            var nodeArray = [];
            for (var iDoc = 0; iDoc < documents.length; iDoc++) {
                var nodeObject = {
                        node: {
                            location: documentsJSON[iDoc].folder,
                            category: {
                                attribute: [
                                    { '#text': documentsJSON[iDoc].docnumber, '@name': "Document Number" }
                                    ],
                                '@name': "ACME",
                            },
                            acl: buildACLnode(documentsJSON[iDoc].docnumber, GroupsACLJSON),
                            '@type': "document",
                            '@action': "create",
                            }
                    };
                nodeArray.push(nodeObject);
            };
            return nodeArray;
        }
    
        xmlObjectElement = buildXML(documentsJSON);
    
        // writing our elements in the xml file using the XML object:
        var ele = xmlObjectImporter.ele(xmlObjectElement);
    
        console.log(xmlObjectImporter.toString({ 
            pretty: true 
        }));