XML转换成JSON

简介: XML转换成JSON

说在前面

相信大家对 XML 都不会很陌生了,XML 被设计用来结构化、存储以及传输信息。最近在开发过程中发现,有一些旧接口返回的数据格式即是 XML 的格式,因此需要我们对返回的 XML 数据进行解析,转换成我们好处理的 JSON 数据结构,对此我花了一点时间写了一个简单的 XML 转换 JSON 格式的方法,所以也就有了今天的这一篇文章,虽然实现起来并不难,但还是希望这一篇文章可以对有需要的同学起到一丢丢的帮助。

XML 简介

什么是 XML

  • XML 指可扩展标记语言(EXtensible Markup Language)。
  • XML 是一种很像 HTML 的标记语言。
  • XML 的设计宗旨是传输数据,而不是显示数据。
  • XML 标签没有被预定义。您需要自行定义标签。
  • XML 被设计为具有自我描述性。
  • XML 是 W3C 的推荐标准。

XML 和 HTML 看起来是类似的,但其实他们是不同的,XML 和 HTML 为不同的目的而设计:

  • XML 被设计用来传输和存储数据,其焦点是数据的内容。
  • HTML 被设计用来显示数据,其焦点是数据的外观。

HTML 旨在显示信息,而 XML 旨在传输信息。

XML 用途

XML 应用于 Web 开发的许多方面,常用于简化数据的存储和共享。

  • XML 把数据从 HTML 分离

如果您需要在 HTML 文档中显示动态数据,那么每当数据改变时将花费大量的时间来编辑 HTML。

通过 XML,数据能够存储在独立的 XML 文件中。这样您就可以专注于使用 HTML/CSS 进行显示和布局,并确保修改底层数据不再需要对 HTML 进行任何的改变。

通过使用几行 JavaScript 代码,您就可以读取一个外部 XML 文件,并更新您的网页的数据内容。

  • XML 简化数据共享

在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。

XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。

这让创建不同应用程序可以共享的数据变得更加容易。

  • XML 简化数据传输

对开发人员来说,其中一项最费时的挑战一直是在互联网上的不兼容系统之间交换数据。

由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。

XML 结构

  • XML 文档实例

XML 文档使用简单的具有自我描述性的语法:

<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

第一行是 XML 声明。它定义 XML 的版本(1.0)和所使用的编码(UTF-8 : 万国码, 可显示各种语言)。

下一行描述文档的根元素(像在说:“本文档是一个便签”):

<note>

接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):

<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>

最后一行定义根元素的结尾:

</note>

您可以假设,从这个实例中,XML 文档包含了一张 Jani 写给 Tove 的便签。

XML 具有出色的自我描述性,您同意吗?

  • XML 文档形成一种树结构

XML 文档必须包含根元素。该元素是所有其他元素的父元素。

XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。

所有的元素都可以有子元素:

<root>
<child>
<subchild>.....</subchild>
</child>
</root>

父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。

所有的元素都可以有文本内容和属性(类似 HTML 中)。

实现思路

简单地对 XML 结构进行了一个复习之后,我们便可以开始准备编写我们的转换工具了:

原生手写

  • 1、找出 XML 中的标签

这里我们只需要简单的对 xml 字符串进行一次遍历,遍历到<时则说明遍历到标签了,我们只需要将其后面的字符串记录起来,直到遇到>时则说明当前标签结束,左标签和右标签我们可以通过/来做区分,以/开头的标签即为右标签。

  • 2、找出标签对中的值

在第一步中我们可以找到所有的标签,在遇到左标签时,我们需要判断其标签内部是否还内嵌了其他标签,这里我们可以通过递归的方式来实现。

完整代码如下:

const XMLToJSON = (XMLData = "") => {
  let ind = 0,
    obj = {};
  const XMLParse = (obj = {}) => {
    let value = "",
      tag = "";
    //遍历xml字符串
    while (ind < XMLData.length) {
      //正在遍历标签内的值,记录标签名
      if (XMLData[ind] === "<" || (tag && XMLData[ind] !== ">")) {
        if (XMLData[ind] === "<") ind++;
        tag += XMLData[ind];
      } else if (XMLData[ind] === ">") {
        //获取到完整的标签名
        //通过rowNum属性来判断是否为数组,有rowNum属性的即为数组
        const rowNum = tag.split(" ")[1] || "";
        tag = tag.split(" ")[0];
        if (tag[0] !== "/") {
          ind++;
          //同一层级当前标签为出现过且不包含rowNum属性,将其处理为对象
          if (obj[tag] === undefined && !rowNum.includes("rowNum")) {
            obj[tag] = {};
            const val = XMLParse(obj[tag], [tag]);
            if (val) obj[tag] = val;
            if (JSON.stringify(obj[tag]) === "{}") {
              obj[tag] = "";
            }
          } else {
            //同一层级下拥有多个同名标签或包含rowNum属性,将其处理为数组
            if (obj[tag] === undefined) obj[tag] = [{}];
            else if (Array.isArray(obj[tag])) obj[tag].push({});
            else obj[tag] = [obj[tag], {}];
            const objInd = obj[tag].length - 1;
            //递归处理标签内的嵌套标签或提取值
            const val = XMLParse(obj[tag][objInd]);
            //有标签值的直接赋值,如:<a>111</a> -> {a:111}
            if (val) obj[tag][objInd] = val;
            //无子节点的赋空值
            if (JSON.stringify(obj[tag][objInd]) === "{}") {
              obj[tag][objInd] = "";
            }
          }
        } else {
          //闭合标签,结束递归返回获取到的值
          return value;
        }
        tag = "";
        value = "";
      } else {
        value += XMLData[ind];
      }
      ind++;
    }
  };
  XMLParse(obj);
  return obj;
};

当然,有 XML 转 JSON 的话,那 JSON 不得也要准备上:

JSONToXML = (JSONData = {}) => {
  if (!JSONData) return "";
  let res = "";
  const JSONParse = (obj) => {
    for (const key in obj) {
      if (Array.isArray(obj[key])) {
        obj[key].forEach((item, index) => {
          res += `<${key} rowNum="${index}">${item}</${key}>`;
        });
      } else if (typeof obj[key] === "object") {
        res += `<${key}>`;
        JSONParse(obj[key]);
        res += `</${key}>`;
      } else {
        res += `<${key}>${obj[key] || ""}</${key}>`;
      }
    }
  };
  JSONParse(JSONData);
  return res;
};
  • 跑下试试
const xmlData =
  '<res><a></a><b></b><c><d rowNum="0">111</d></c><e>222</e></res>';
const jsonData = {
  res: {
    a: "",
    b: "",
    c: {
      d: ["111"],
    },
    e: "222",
  },
};
console.log(XMLToJSON(xmlData));
console.log(JSONToXML(jsonData));

结果如下图:

写到这里是不是就该结束了?不,写完这个方法之后我才发现原来现在浏览器都有内建的 XML 解析器。XML 解析器可以把 XML 文档转换为 XML DOM 对象 - 可通过 JavaScript 操作的对象。

XML 解析器

  • Internet Explorer 使用 loadXML() 方法来解析 XML 字符串,而其他浏览器使用 DOMParser 对象。
const xmlData =
  '<res><a></a><b></b><c><d rowNum="0">111</d></c><e>222</e></res>';
if (window.DOMParser) {
  parser = new DOMParser();
  xmlDoc = parser.parseFromString(xmlData, "text/xml");
} // Internet Explorer
else {
  xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async = false;
  xmlDoc.loadXML(xmlData);
}

结果如下图:

这样的话我们可以利用浏览器自带的 XML 解析器来完成 XML 数据的转换:

const deepParse = (xmlDoc, tagName) => {
  const xmlObj = {};
  const rootDom = xmlDoc.getElementsByTagName(tagName)[0];
  for (let i = 0; i < rootDom.children.length; i++) {
    const child = rootDom.children[i];
    if (child.children.length > 0) {
      xmlObj[child.nodeName] = deepParse(xmlDoc, child.nodeName);
    } else {
      if (xmlObj[child.nodeName] !== undefined) {
        if (!Array.isArray(xmlObj[child.nodeName])) {
          xmlObj[child.nodeName] = [xmlObj[child.nodeName]];
        }
        xmlObj[child.nodeName].push(child.textContent);
      } else {
        xmlObj[child.nodeName] = child.textContent;
      }
    }
  }
  return xmlObj;
};
const parseXmlData = (xmlStr, tagName = "rtInfo") => {
  const parser = new DOMParser();
  const xmlDoc = parser.parseFromString(xmlStr, "text/xml");
  const xmlObj = deepParse(xmlDoc, tagName);
  return xmlObj;
};

结果如下图:

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。

目录
相关文章
|
1月前
|
XML 存储 JSON
Python学习 -- 常用数据交换格式(CSV、XML、JSON)
Python学习 -- 常用数据交换格式(CSV、XML、JSON)
15 0
|
1月前
|
XML JSON 数据格式
xml与JSON的区别
xml与JSON的区别
19 1
|
2月前
|
XML 存储 JSON
如何快速实现XML与JSON转换
XML与JSON之间的转换常常用于以下场景: 1.数据交换:当需要在不同的系统、平台或服务之间进行数据交换时,常常会使用XML或JSON进行数据的序列化和反序列化。比如,一个Web服务可能需要返回数据给一个移动应用,这时,数据就可以通过XML或JSON格式进行传输。
|
24天前
|
XML 机器学习/深度学习 JSON
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
18 0
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
|
1月前
|
XML 存储 JSON
详细比较JSON和XML这两种数据格式
详细比较JSON和XML这两种数据格式
48 2
|
2月前
|
XML 存储 JSON
实现XML与JSON转换,实测这个方法最便捷
XML和JSON是当今最常用的两种数据格式,在数据交换和存储领域占有重要地位。XML以其树状结构和可扩展性被广泛使用,而JSON则以其轻量级和易读性受到开发者的青睐。有时候,为了更好地利用它们的优点解决数据共享、数据处理和数据存储等问题,我们需要将这两种格式进行转换。本文将介绍如何使用Java实现将XML格式转换成JSON格式。
|
2月前
|
XML 存储 JSON
C# 对象存储 (轻松实现序列化 | Xml | Json | 加密 | 压缩 | 注册表 | Redis)
开发时经常会遇到需要保存配置的情况,最常见的实现方式是将对象序列化成Json,再写入文件并保存到本地磁盘。 本文将使用开源库**ApeFree.DataStore**来替换原有的对象存储过程,实现一个可以随意切换存储方式的对象存储方法。 ApeFree.DataStore是一款可配置的对象存储库,支持在不同平台/介质中对内存中的对象进行存储与还原(如本地存储、注册表存储)。支持配置序列化格式(如Json、Xml),支持配置压缩算法(如GZip、Defalte),支持配置加密算法(如AES、RSA)。
47 0
C# 对象存储 (轻松实现序列化 | Xml | Json | 加密 | 压缩 | 注册表 | Redis)
|
2月前
|
XML 存储 JSON
C# | JSON格式与XML格式互相转换
JSON格式与XML格式是目前互联网上使用最为广泛的数据交换格式之一,而两种格式各自有着自己的特点和优势。 在实际开发中,我们经常需要将数据在不同的系统或模块之间进行传递和转换,而JSON格式和XML格式的互相转换是一项非常基础和必要的技能。 同时,对于需要将数据存储在不同的介质中的应用场景,比如在移动端本地存储数据,或者在服务器端将数据保存到文件或数据库中,也需要将JSON或XML格式进行相应的转换。 因此,熟练掌握JSON与XML格式互相转换的方法对于开发人员来说是非常重要的。在本文中,我们将介绍常用的JSON和XML互相转换的方法及其实现。
47 0
C# | JSON格式与XML格式互相转换
|
2月前
|
XML 存储 JSON
C# | DataGridView数据转存为Json、XML格式
DataGridView是常用的数据展示组件,而将其转存为Json或XML格式,则可以方便地进行数据的传输和存储。 Json格式具有轻量、易读、易解析等优点,广泛应用于Web开发、API接口传输等场景。 XML格式则具有良好的结构化特性,支持命名空间、数据类型等复杂数据表示方式,被广泛应用于数据交换、配置文件等领域。 因此,将DataGridView数据转存为Json、XML格式,不仅能够方便地进行数据的传输和存储,还能够满足不同场景下的数据需求。 本篇文章将介绍如何将DataGridView数据转存为Json、XML格式,并提供相应的代码示例。
61 0
C# | DataGridView数据转存为Json、XML格式