使用Javascript将XML转换为JSON(并且反向转换)

176

如何将XML转换为JSON,再将其转换回XML?

以下工具效果很好,但不完全一致:

有人遇到过这种情况吗?


12
请解释这些不一致之处。 - Josh Stodola
4
具体而言,涉及将只有1个元素的JSON数组转换为XML。当您将其转换回JSON时,它不会创建一个1元素数组,而是创建了一个对象字面量。我通过使用$.isArray()来检查类型,并在! $.isArray()情况下将其包装在数组中来解决这个问题。 - Jason Suárez
1
xml2json - http://www.fyneworks.com/jquery/xml-to-json/ - 在2013年2月15日14:25 AEST之后出现了500错误。 - ysrb
json2xml的链接已经失效。 - whirlwin
你尝试过这个吗?https://devtoolsonline20190908040816.azurewebsites.net/DevTools/Convert_JSON2XML - GomuGomuNoRocket
显示剩余2条评论
14个回答

128

1
谢谢回复!在我的情况下,JSON是规范表示法,XML仅用于XSLT..这不是我的想法! :) - Jason Suárez
1
这仅适用于浏览器,不适用于node.js或非浏览器环境。还有其他想法吗? - Homer6
1
关于@JasonDenizac在他的帖子中的评论,我不确定如何理解这个链接有助于解决将一个对象而不是一个包含一个项目的数组的问题... - guiomie
1
我发现如果你从json-xml-json开始,这个库可以很好地工作,但是如果你想要xml-json-xml,由于它添加了元数据xml元素如<o>和<e>,所以存在可逆性问题。 - vishr
3
请注意,这是一个Copyleft许可的解决方案。仅适用于编写开源软件时使用。 - Jasper
显示剩余7条评论

56

https://github.com/abdmob/x2js - 这是我的自己写的库(从 http://code.google.com/p/x2js/ 更新了URL):

这个库提供了将XML转换为JSON(JavaScript对象)及其反向操作的JavaScript转换函数。该库非常小,不需要其他附加库。

API 函数:

  • new X2JS() - 创建实例以访问整个库功能,此处还可以指定可选配置选项
  • X2JS.xml2json - 将指定为DOM对象的XML转换为JSON
  • X2JS.json2xml - 将JSON转换为XML DOM对象
  • X2JS.xml_str2json - 将指定为字符串的XML转换为JSON
  • X2JS.json2xml_str - 将JSON转换为XML字符串

在线演示:http://jsfiddle.net/abdmob/gkxucxrj/1/

var x2js = new X2JS();
function convertXml2JSon() {
    $("#jsonArea").val(JSON.stringify(x2js.xml_str2json($("#xmlArea").val())));
}

function convertJSon2XML() {
    $("#xmlArea").val(x2js.json2xml_str($.parseJSON($("#jsonArea").val())));
}

convertXml2JSon();
convertJSon2XML();
$("#convertToJsonBtn").click(convertXml2JSon);
$("#convertToXmlBtn").click(convertJSon2XML);

1
你好,你是如何解决这个问题的?当你在一个对象中有一个对象字面量时,如果有n>1个对象,你就需要使用数组。这使得在模板中使用XML转JSON对象变得困难... - guiomie
是的,你应该使用一些技巧,这取决于你对XML结构的了解(因为这里没有XSD)。使用<node>...<node>_asArray语法来始终将你的节点作为数组(序列)访问。 - abdolence
1
示例:// XML字符串转JSON var xmlText =“<MyOperation> <test> Success </ test> <test2> <item> ddsfg </ item> <item> dsdgfdgfd </ item> </ test2> </ MyOperation>”; var jsonObj = X2JS.xml_str2json(xmlText); alert(jsonObj.MyOperation.test); alert(jsonObj.MyOperation.test_asArray [0]); - abdolence
我的主要问题是,当我将我的JSON转换回XML时,JSON中充满了额外的属性,而字符串XML版本保留了所有无用的内容。它有各种逗号和空格... - guiomie
这是你自己的库吗?如果是,请在你的回答中添加一条注释。这是一个好习惯。 - Jasper
显示剩余5条评论

39

这些答案对我帮助很大,使我完成了这个函数:

function xml2json(xml) {
  try {
    var obj = {};
    if (xml.children.length > 0) {
      for (var i = 0; i < xml.children.length; i++) {
        var item = xml.children.item(i);
        var nodeName = item.nodeName;

        if (typeof (obj[nodeName]) == "undefined") {
          obj[nodeName] = xml2json(item);
        } else {
          if (typeof (obj[nodeName].push) == "undefined") {
            var old = obj[nodeName];

            obj[nodeName] = [];
            obj[nodeName].push(old);
          }
          obj[nodeName].push(xml2json(item));
        }
      }
    } else {
      obj = xml.textContent;
    }
    return obj;
  } catch (e) {
      console.log(e.message);
  }
}
只要您传入一个 jQuery DOM/XML 对象,对我而言是这样的:
Jquery(this).find('content').eq(0)[0]

其中content是我存储XML的字段。


救了我的一天!几乎所有其他的例子都不起作用,甚至是 JSFiddle 的例子! - Arham Anees
目前为止,工作得非常好。谢谢。 - strix25
错误:xml.children 未定义。 - Tadas Majeris
看起来你没有获取任何元素属性,而几乎所有我需要的数据都存储在那里。 - Travis Bemrose

21

我创建了一个基于正则表达式的递归函数,如果您不想安装库并理解发生的情况背后的逻辑:

我基于正则表达式创建的递归函数,无需安装任何库即可使用,并且可以理解其中的逻辑:

const xmlSample = '<tag>tag content</tag><tag2>another content</tag2><tag3><insideTag>inside content</insideTag><emptyTag /></tag3>';
console.log(parseXmlToJson(xmlSample));

function parseXmlToJson(xml) {
    const json = {};
    for (const res of xml.matchAll(/(?:<(\w*)(?:\s[^>]*)*>)((?:(?!<\1).)*)(?:<\/\1>)|<(\w*)(?:\s*)*\/>/gm)) {
        const key = res[1] || res[3];
        const value = res[2] && parseXmlToJson(res[2]);
        json[key] = ((value && Object.keys(value).length) ? value : res[2]) || null;

    }
    return json;
}

每个循环的正则表达式解释:

  • res[0] - 返回xml(不变)
  • res[1] - 返回xml标签名称
  • res[2] - 返回xml内容
  • res[3] - 返回自关闭标签的xml标签名称。例如:<tag />

您可以在此处检查正则表达式的工作方式: https://regex101.com/r/ZJpCAL/1

注意:如果json具有未定义值的键,则该键将被删除。这就是为什么我在第9行插入了null的原因。


1
深度嵌套的XML字符串值未按预期工作。 - sankar muniyappa
@sankarmuniyappa请写一个没能成功的例子,这样我就可以修复它 :) - MasterPiece
如何使用此XML使其工作? 标签内容另一个内容内部内容 标签内容另一个内容内部内容 ``` - timy
该函数针对您的情况返回了正确的输出: {"chan":{"item":{"tag":"标签内容","tag2":"另一个内容","tag3":{"insideTag":"内部内容","emptyTag":null}}}} - MasterPiece
@MasterPiece 嗯,在 https://docs.scriptable.app 中,该函数仅返回最后一个项目:{"tag":"tag2 content","tag2":"another content 2","tag3":{"insideTag":"inside content 2","emptyTag":null}} - timy
如果我使用模板字面量在多行中写入以下内容: <tag3> <insideTag>内部内容</insideTag> <emptyTag /> </tag3> 它不会返回嵌套的JSON,而是将所有键分开。 - yograj tandel

5

我只需获取XML文件中的单个值,就使用了xmlToJson函数。
但是,我发现如果XML文件只包含一个值,那么采用以下方法会更加简便:

let xml =
'<person>' +
  ' <id>762384324</id>' +
  ' <firstname>Hank</firstname> ' +
  ' <lastname>Stone</lastname>' +
'</person>';

let getXmlValue = function(str, key) {
  return str.substring(
    str.lastIndexOf('<' + key + '>') + ('<' + key + '>').length,
    str.lastIndexOf('</' + key + '>')
  );
}


alert(getXmlValue(xml, 'firstname')); // gives back Hank


1
保持工作!这绝对有帮助到我了! - RixTheTyrunt
非常感谢您的鼓励 :) - Nebulosar
没问题!!!BD - RixTheTyrunt

5
您还可以使用txml。它可以解析为由简单对象构成的DOM,并进行字符串化。结果中的内容将被修剪。因此,原有白空格的格式将会丢失。但这非常适合用于HTML的缩小化。
const xml = require('txml');
const data = `
<tag>tag content</tag>
<tag2>another content</tag2>
<tag3>
  <insideTag>inside content</insideTag>
  <emptyTag />
</tag3>`;

const dom = xml(data); // the dom can be JSON.stringified

xml.stringify(dom); // this will return the dom into an xml-string

免责声明:本人是txml的作者,该解析器是javascript中最快速的xml解析器。


1
这是一个非常好的替代fast-xml-parser的选择,使用simplify,它不会随意将字符串转换为数字(例如将"1.0"转换为11.)。 - Daniel

4

前一段时间我为我的电视观看列表应用程序编写了这个工具https://bitbucket.org/surenrao/xml2json,希望这也能有所帮助。

简介:一个库不仅可以将 XML 转换为 JSON,而且还易于调试(无循环错误)和重新创建 JSON 返回到 XML。特点:- 将 XML 解析为 JSON 对象。打印 JSON 对象返回到 XML。可用于将 XML 保存在 IndexedDB 中作为 X2J 对象。打印 JSON 对象。


@kleopatra 这个链接指向将 XML 转换为 JSON 的工具。它不是一个参考,而是资源的实际链接。不确定我还应该怎么做 :) - surya

3

用6行简单的ES6代码:

xml2json = xml => {                                                                                                                                                     
  var el = xml.nodeType === 9 ? xml.documentElement : xml                                                                                                               
  var h  = {name: el.nodeName}                                                                                                                                          
  h.content    = Array.from(el.childNodes || []).filter(e => e.nodeType === 3).map(e => e.textContent).join('').trim()                                                  
  h.attributes = Array.from(el.attributes || []).filter(a => a).reduce((h, a) => { h[a.name] = a.value; return h }, {})                                                 
  h.children   = Array.from(el.childNodes || []).filter(e => e.nodeType === 1).map(c => h[c.nodeName] = xml2json(c))                                                    
  return h                                                                                                                                                              
}  

使用以下命令 echo "xml2json_example()" | node -r xml2json.es6 进行测试,源代码位于https://github.com/brauliobo/biochemical-db/blob/master/lib/xml2json.es6


11
好的,我会尽力进行翻译。6个简单的行,再加上来自 xml2json 的2000行内容。 - ShortFuse
1
@ShortFuse 唯一的依赖项是 xmldom,一个 XML 解析器。这不使用来自 npm 的 xml2json,尽管名称相同。 - brauliobo

1

免责声明:本人已编写fast-xml-parser

Fast XML Parser可以帮助将XML转换为JSON,反之亦然。以下是示例:

var options = {
    attributeNamePrefix : "@_",
    attrNodeName: "attr", //default is 'false'
    textNodeName : "#text",
    ignoreAttributes : true,
    ignoreNameSpace : false,
    allowBooleanAttributes : false,
    parseNodeValue : true,
    parseAttributeValue : false,
    trimValues: true,
    decodeHTMLchar: false,
    cdataTagName: "__cdata", //default is 'false'
    cdataPositionChar: "\\c",
};
if(parser.validate(xmlData)=== true){//optional
    var jsonObj = parser.parse(xmlData,options);
}

如果您想将JSON或JS对象解析为XML,则
//default options need not to set
var defaultOptions = {
    attributeNamePrefix : "@_",
    attrNodeName: "@", //default is false
    textNodeName : "#text",
    ignoreAttributes : true,
    encodeHTMLchar: false,
    cdataTagName: "__cdata", //default is false
    cdataPositionChar: "\\c",
    format: false, 
    indentBy: "  ",
    supressEmptyNode: false
};
var parser = new parser.j2xParser(defaultOptions);
var xml = parser.parse(json_or_js_obj);

FXP不仅是XML转JSON转换器。请查看它的自述文件。 - Amit Kumar Gupta

0
这是一个来自文献资料丰富且非常知名的npm库的好工具,它能够很好地执行xml<->js转换:与上面提出的一些(也许全部)解决方案不同,它还可以转换xml注释。请点击这里了解更多信息。
var obj = {name: "Super", Surname: "Man", age: 23};

var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接