将变量或属性值传递给JavaScript对象中的方法将返回“未定义”

时间:2018-07-05 15:24:35

标签: javascript node.js xml-builder

我正在尝试通过2个级联循环从2个JSON对象构建xml文件。在第二个循环中,我找不到如何从上一个循环传递值:

在下面的示例中,我想将“ docnumber”值传递给我的第二个循环(通过GroupsACLJSON),以便从第二个JSON对象构建“ acl”节点,但要使用第二个JSON对象中的“ this.docnumber”父对象属性返回“ undefined”,从而导致一个空的“ 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 :(得分:0)

您有几个未声明的变量,这些变量将在严格模式下运行时导致代码中断。

    for循环中的
  1. ij都需要声明。例如let i = 0
  2. 未声明aclObject。您需要添加一个var声明,例如const aclObject = { ... }

修复这些问题后,至少可以轻松运行代码,至少可以轻松构建xmlObjectElement并执行有效的node()和acl()函数。

已更新

这不会解决xml-builder遍历对象和构建xml的方式,但是可以通过使用Array方法而不是for循环来改善您的功能。因此,您无需使用ij并减少引入错误的机会。

例如,您可以使用.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",
        },
....
})

答案 1 :(得分:0)

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