【问题标题】:Javascript Recursive String AppendJavascript递归字符串追加
【发布时间】:2017-01-28 06:20:27
【问题描述】:

我同时拥有简单和复杂的 JSON 数据,并使用 JavaScript 递归方法将其转换为 XML,如下所示:

var json = [
  {
    "id": "42cfb980-4221-e97f-f85a-f5fcf4d37f02",
    "name": "outer",
    "value": "",
    "attributes": {},
    "subNodes": [
      {
        "id": "d0794639-5568-3728-11a4-676eb100b07a",
        "name": "inner",
        "value": "inner vlaue",
        "attributes": {},
        "subNodes": []
      }
    ]
  }
];

function prepareXmlOutput(appendTo, obj) {
        var i, k, attributeString = '';

        for (i in obj) {
            if (obj[i].attributes.length > 0) {
                for (k in obj[i].attributes) {
                    attributeString += ((obj[i].attributes[k].name != '') ? obj[i].attributes[k].name+'="'+obj[i].attributes[k].value+'"' : '') + ' ';
                }
            }
            if (obj[i].subNodes.length < 1) {
                if (obj[i].value == '') {
                    appendTo += '</' + obj[i].name + attributeString.replace(/~+$/,'') + '>';
                } else {
                    appendTo += '<' + obj[i].name + attributeString.replace(/~+$/,'') + '>' +obj[i].value+ '</' + obj[i].name + '>';
                }

            } else {
                appendTo += '<' + obj[i].name + attributeString.replace(/~+$/,'') + '>';

                appendTo += prepareXmlOutput(appendTo, obj[i].subNodes);

                appendTo += '</' + obj[i].name + '>';
            }
        }
        return appendTo;
    }

prepareXmlOutput('', json);

这产生的 xml 非常好,但有一个问题。这是它给我的 XML:

"<outer><outer><inner>inner vlaue</inner></outer>"

问题是,它重复了第一个节点。为什么会这样?用开发工具试了很多调试,发现完成这个栈后光标直接进入return语句:

appendTo += prepareXmlOutput(appendTo, obj[i].subNodes);

【问题讨论】:

    标签: javascript arrays json xml


    【解决方案1】:

    替换这一行:

    appendTo += prepareXmlOutput(appendTo, obj[i].subNodes);
    

    用这个:

    appendTo += prepareXmlOutput('', obj[i].subNodes);
    

    因为它必须独立于累积的appendTo 为子节点创建 XML 字符串。然后使用+= 将结果(返回值)附加到它。在您的代码中,结果被附加了两次(在函数内部附加到appendTo,然后返回已经附加的结果以再次使用+= 附加)。对于 N 的深度,外部元素重复 N + 1 次,第二个外部元素重复 N 次,...以此类推,直到不会重复的内部元素。

    您遇到的错误示例:考虑appendTo'&lt;outer&gt;',您将其作为参数传递给函数调用,当调用结束时,appendTo 被附加到'&lt;inner&gt;',它返回'&lt;outer&gt;&lt;inner&gt;',然后您使用+= 附加到appendTo(即'&lt;outer&gt;')的前一个值,所以现在appendTo 变为'&lt;outer&gt;&lt;outer&gt;&lt;inner&gt;'(外部元素重复2 次,因为它被传递给调用一次(一级下面)) 如果下面有 N 个级别,那么 appendTo 将被传递给调用 N 次,如下所示:

    • 通过 N°1:appendTo = '&lt;outer&gt;'
    • 2号通行证:appendTo = '&lt;outer&gt;&lt;outer&gt;&lt;inner&gt;'
    • 通过 N°3:appendTo = '&lt;outer&gt;&lt;outer&gt;&lt;outer&gt;&lt;inner&gt;&lt;inner&gt;'
    • ...

    【讨论】:

    • 太棒了。它工作正常,但你能详细说明一下吗?它是如何工作的。我的实施有什么问题?
    • 我猜你只能将obj作为输入参数,并在函数内部声明appendTo
    • @ManishJangir 我添加了一个示例。不是 100% 准确,但你会明白的。
    【解决方案2】:

    只是为了一些变化;你不妨这样做;

    var json = [
      {
        "id": "42cfb980-4221-e97f-f85a-f5fcf4d37f02",
        "name": "outer",
        "value": "",
        "attributes": {},
        "subNodes": [
          {
            "id": "d0794639-5568-3728-11a4-676eb100b07a",
            "name": "in01",
            "value": "inner value",
            "attributes": {color:"red"},
            "subNodes": [{
                           "id": "d0794639-5568-3728-11a4-676eb100b07a",
                           "name": "in02",
                           "value": "more inner value",
                           "attributes": {color:"blue"},
                           "subNodes": [{
                                          "id": "d0794639-5568-3728-11a4-676eb100b07a",
                                          "name": "in03",
                                          "value": "most innest value",
                                          "attributes": {color:"pink"},
                                          "subNodes": []
                                        }]
                         }]
          },
          {
            "id": "d0794639-5568-3728-11a4-676eb100b07b",
            "name": "in11",
            "value": "another inner value",
            "attributes": {color:"orange"},
            "subNodes": [{
                           "id": "d0794639-5568-3728-11a4-676eb100b07a",
                           "name": "in12",
                           "value": "more inner value",
                           "attributes": {color:"brown"},
                           "subNodes": []
                         }]
          }
         ]
      }
    ],
    
    parseXML = (a, r = "") => a.length ? parseXML(a.slice(1), r + Object.keys(a[0].attributes)
                                                                        .reduce((s,k) => s + " " + k + "=\"" + a[0].attributes[k] + "\"", "<" + a[0].name)
                                                                        + ">"
                                                                        + a[0].value
                                                                        + parseXML(a[0].subNodes,"")
                                                                        + "</"
                                                                        + a[0].name
                                                                        + ">")
                                       : r;
    console.log(parseXML(json));

    【讨论】:

      猜你喜欢
      • 2019-08-07
      • 2020-08-09
      • 1970-01-01
      • 2013-06-15
      • 2014-02-19
      • 2021-12-11
      • 2017-12-15
      • 2011-12-24
      • 2011-08-24
      相关资源
      最近更新 更多