Передача значения переменной или свойства методу в объекте JavaScript возвращает «неопределенное» - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь построить файл XML из 2 объектов JSON через 2 каскадных цикла. Во втором цикле я не могу найти, как передать значение из предыдущего цикла:

В приведенном ниже примере я хотел бы передать значение "docnumber" во второй цикл (через GroupsACLJSON), чтобы построить узел "acl" из второго объекта JSON, но с использованием "this.docnumber" из Свойство родительского объекта возвращает значение «неопределенное», что приводит к пустому узлу «acl».

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
}));

Вот вывод, который я бы ожидал от этого:

<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>

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Следуя совету nxSolari, я переписал код, используя 2 функции вместо большого объекта и методов, и получил желаемый результат. Я до сих пор не понимаю, как код проходит через объекты и методы, но вот новый рабочий код:

    '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 
    }));
0 голосов
/ 05 июля 2018

У вас есть несколько необъявленных переменных, которые приведут к разрыву кода при работе в строгом режиме.

  1. i и j в ваших циклах for оба должны быть объявлены. например let i = 0.
  2. aclObject не объявлено. Вам нужно добавить объявление var, например const aclObject = { ... }.

После исправления я без проблем запустил ваш код, по крайней мере, у меня не было проблем с созданием xmlObjectElement и выполнением функций node () и acl (), которые работали.

ОБНОВЛЕНО

Это не исправит способ, которым xml-builder обходит ваш объект и строит xml, но ваши функции можно улучшить, используя методы Array вместо for for. Вам не нужно было бы использовать i или j и снизить вероятность появления ошибки по этой причине.

Например, вы можете легко заменить оба цикла с помощью .map(). См https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map.

var xmlObjectElement = {
  node: function () {
    return documentsJSON.map((document) => {
      // populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
      return {
        location: document.folder,
        category: {
          attribute: [
            { '#text': document.docnumber, '@name': "Document Number" }
          ],
          '@name': "ACME",
        },
....
})
...