手写XML转JSON:从结构解析到数据转换全指南
在数据交互和API开发中,XML和JSON是两种常见的数据格式,虽然JSON因其轻量和易读性更受青睐,但许多系统仍使用XML作为数据交换格式,本文将详细介绍如何手写代码将XML转换为JSON,帮助开发者理解两种格式之间的转换逻辑。
理解XML和JSON的基本结构
在开始转换之前,我们需要明确两种格式的核心差异:
- XML:使用标签嵌套表示层级关系,如
<root><child>value</child></root> - JSON:使用键值对和数组表示数据结构,如
{"root": {"child": "value"}}
转换的关键在于:
- 将XML标签名转换为JSON的键名
- 将XML属性转换为JSON对象的属性
- 处理XML的文本内容和嵌套结构
- 处理命名空间等复杂情况
手写转换的核心步骤
解析XML文档
首先需要解析XML字符串,可以使用DOM或SAX方式,这里以DOM为例:
function parseXML(xmlString) {
const parser = new DOMParser();
return parser.parseFromString(xmlString, "text/xml");
}
递归转换节点
XML的层级结构需要递归处理:
function xmlNodeToJson(node) {
let result = {};
// 处理节点属性
if (node.attributes && node.attributes.length > 0) {
result = {};
for (let i = 0; i < node.attributes.length; i++) {
const attr = node.attributes[i];
result[`@${attr.name}`] = attr.value;
}
}
// 处理子节点
if (node.childNodes && node.childNodes.length > 0) {
for (let i = 0; i < node.childNodes.length; i++) {
const child = node.childNodes[i];
if (child.nodeType === Node.TEXT_NODE) {
// 处理文本节点
const text = child.textContent.trim();
if (text) {
if (Object.keys(result).length === 0) {
return text;
}
result['#text'] = text;
}
} else if (child.nodeType === Node.ELEMENT_NODE) {
// 处理元素节点
const childJson = xmlNodeToJson(child);
if (result[child.nodeName]) {
// 处理同名节点数组
if (!Array.isArray(result[child.nodeName])) {
result[child.nodeName] = [result[child.nodeName]];
}
result[child.nodeName].push(childJson);
} else {
result[child.nodeName] = childJson;
}
}
}
}
return result;
}
处理特殊情况
需要考虑以下特殊情况:
- 空节点:
<empty/>应转换为{"empty": ""}或{"empty": null} - :
<p>text<b>bold</b>more</p>应保留文本和标签结构 - 命名空间:处理带命名空间的XML节点
function handleEmptyNode(node) {
if (node.childNodes.length === 0 && !node.attributes.length) {
return null;
}
return xmlNodeToJson(node);
}
完整转换函数示例
function xmlToJson(xmlString) {
const xmlDoc = parseXML(xmlString);
const rootNode = xmlDoc.documentElement;
return xmlNodeToJson(rootNode);
}
测试用例
const xmlString = `
<root>
<person id="1">
<name>John Doe</name>
<age>30</age>
<hobbies>
<hobby>Reading</hobby>
<hobby>Swimming</hobby>
</hobbies>
<address>
<city>New York</city>
<zip>10001</zip>
</address>
</person>
<person id="2">
<name>Jane Smith</name>
<age>25</age>
</person>
</root>
`;
console.log(JSON.stringify(xmlToJson(xmlString), null, 2));
高级处理技巧
-
处理命名空间:
function removeNamespace(node) { if (node.nodeType === Node.ELEMENT_NODE) { node.nodeName = node.localName || node.nodeName; } // 递归处理子节点 while (node.firstChild) { removeNamespace(node.firstChild); node.parentNode.appendChild(node.firstChild); } } -
自定义转换规则:
function customConverter(node, json) { // 根据业务需求自定义转换逻辑 if (node.nodeName === 'date') { return new Date(node.textContent); } return json; }
性能优化建议
- 对于大型XML文件,考虑使用流式解析(SAX方式)
- 缓存已解析的节点,避免重复处理
- 使用对象池技术减少内存分配
常见问题与解决方案
- CDATA处理:需要特别识别
<![CDATA[ ]]>部分 - 特殊字符转义:确保XML中的特殊字符在JSON中正确转义
- 循环引用:避免XML中的循环引用导致无限递归
通过以上步骤,我们可以实现一个健壮的XML到JSON的手写转换器,虽然已有成熟的库(如xml2js)可以完成这项工作,但手写转换过程能帮助我们更理解两种数据格式的本质差异,为处理复杂场景打下坚实基础,在实际开发中,可以根据具体需求调整转换逻辑,确保数据转换的准确性和完整性。



还没有评论,来说两句吧...