131 lines
4.3 KiB
JavaScript
131 lines
4.3 KiB
JavaScript
|
/**
|
|||
|
* XML工具类,包含XML处理相关的方法
|
|||
|
* @type {module}
|
|||
|
*/
|
|||
|
export class XmlUtils {
|
|||
|
/**
|
|||
|
* HTML转义
|
|||
|
*/
|
|||
|
static escapeHtml(unsafe) {
|
|||
|
return unsafe
|
|||
|
.replace(/&/g, "&")
|
|||
|
.replace(/</g, "<")
|
|||
|
.replace(/>/g, ">")
|
|||
|
.replace(/"/g, """)
|
|||
|
.replace(/'/g, "'");
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 确保CommandList元素符合特定格式
|
|||
|
*/
|
|||
|
static ensureCommandListFormat(xmlDoc) {
|
|||
|
// 如果没有rootElement,返回null
|
|||
|
if (!xmlDoc) return null;
|
|||
|
|
|||
|
const rootElement = xmlDoc.documentElement;
|
|||
|
|
|||
|
// 查找或创建CommandList元素
|
|||
|
let commandListElement = rootElement.querySelector('CommandList');
|
|||
|
if (!commandListElement) {
|
|||
|
commandListElement = xmlDoc.createElement('CommandList');
|
|||
|
rootElement.appendChild(commandListElement);
|
|||
|
}
|
|||
|
|
|||
|
return commandListElement;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 格式化XML
|
|||
|
*/
|
|||
|
static formatXml(xml) {
|
|||
|
const parser = new DOMParser();
|
|||
|
const xmlDoc = parser.parseFromString(xml, 'application/xml');
|
|||
|
|
|||
|
return XmlUtils.formatNode(xmlDoc, 0);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 递归处理XML节点
|
|||
|
*/
|
|||
|
static formatNode(node, level) {
|
|||
|
if (!node) return '';
|
|||
|
|
|||
|
let result = '';
|
|||
|
const indentStr = ' '.repeat(level);
|
|||
|
|
|||
|
// 处理不同类型的节点
|
|||
|
switch (node.nodeType) {
|
|||
|
case Node.DOCUMENT_NODE:
|
|||
|
// 文档节点,处理子节点
|
|||
|
result = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|||
|
for (let i = 0; i < node.childNodes.length; i++) {
|
|||
|
result += XmlUtils.formatNode(node.childNodes[i], level);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case Node.ELEMENT_NODE:
|
|||
|
// 元素节点
|
|||
|
result += indentStr + '<' + node.nodeName;
|
|||
|
|
|||
|
// 处理属性
|
|||
|
for (let i = 0; i < node.attributes.length; i++) {
|
|||
|
const attr = node.attributes[i];
|
|||
|
result += ' ' + attr.name + '="' + attr.value + '"';
|
|||
|
}
|
|||
|
|
|||
|
if (node.childNodes.length === 0) {
|
|||
|
// 没有子节点,使用自闭合标签
|
|||
|
result += ' />\n';
|
|||
|
} else {
|
|||
|
result += '>';
|
|||
|
|
|||
|
let hasElement = false;
|
|||
|
let textContent = '';
|
|||
|
|
|||
|
// 检查是否只有文本内容
|
|||
|
for (let i = 0; i < node.childNodes.length; i++) {
|
|||
|
if (node.childNodes[i].nodeType === Node.ELEMENT_NODE) {
|
|||
|
hasElement = true;
|
|||
|
break;
|
|||
|
} else if (node.childNodes[i].nodeType === Node.TEXT_NODE) {
|
|||
|
textContent += node.childNodes[i].nodeValue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (hasElement) {
|
|||
|
// 有元素子节点,换行并增加缩进
|
|||
|
result += '\n';
|
|||
|
for (let i = 0; i < node.childNodes.length; i++) {
|
|||
|
result += XmlUtils.formatNode(node.childNodes[i], level + 1);
|
|||
|
}
|
|||
|
result += indentStr;
|
|||
|
} else {
|
|||
|
// 只有文本内容,不换行
|
|||
|
result += textContent.trim();
|
|||
|
}
|
|||
|
|
|||
|
result += '</' + node.nodeName + '>\n';
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case Node.TEXT_NODE:
|
|||
|
// 文本节点,去除空白文本节点
|
|||
|
const text = node.nodeValue.trim();
|
|||
|
if (text) {
|
|||
|
result += text;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case Node.COMMENT_NODE:
|
|||
|
// 注释节点
|
|||
|
result += indentStr + '<!--' + node.nodeValue + '-->\n';
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
// 其他类型节点
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
}
|