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

目录
相关文章
|
6月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
75 1
|
7月前
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
112 1
|
6月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
243 61
C# 中的 XML 与 JSON 数据处理
|
5月前
|
XML JSON 数据可视化
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
本文详细介绍了不同数据集格式之间的转换方法,包括YOLO、VOC、COCO、JSON、TXT和PNG等格式,以及如何可视化验证数据集。
960 1
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
|
10月前
|
XML JSON 前端开发
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(支持并行网关)
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(支持并行网关)
538 3
|
5月前
|
XML JSON 前端开发
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
1054 0
|
7月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
243 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
7月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
98 0
|
10月前
|
XML JSON 前端开发
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(排它条件网关)
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(排它条件网关)
174 3
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(排它条件网关)
|
10月前
|
XML JSON 前端开发
初学者指南:JSON 和 XML 的区别
当我们讨论数据交换格式时,JSON(JavaScript对象表示法)和 XML(可扩展标记语言)无疑是最受欢迎的两种选择。这两者各有优点和缺点,根据具体的应用场景,选择合适的格式可以显著提高开发效率和系统性能。