Vue 3中解析XML需用DOMParser并指定"text/xml"类型,解析后转为JS对象再响应式处理,失败时检查parsererror元素,fetch应使用text()而非json(),避免v-html直接渲染XML。
XML 数据不能直接用 JSON.parse(),必须用浏览器原生的 DOMParser。Vue 3 的响应式系统不自动追踪 XML 节点树变化,所以解析后应转为普通 JS 对象再交给 ref 或 reactive。
XMLHttpRequest.responseXML 或 fetch 的 Response.body
"text/xml",否则解析失败或返回空文档DOMParser 不抛异常,需手动检查 parsererror 元素:const doc = new DOMParser().parseFromString(xmlStr, "text/xml");
if (doc.querySelector("parsererror")) {
console.error("XML 解析出错", doc.querySelector("parsererror").textContent);
}直接 await res.text() 比 res.json() 更可靠——XML 响应头常为 text/xml 或 application/xml,但 res.json() 会报 MIME 类型错误。
onMounted 中裸写 fetch,建议封装成可复用的 useXmlFetcher 组合函数Access-Control-Allow-Origin,否则 fetch 直接拒绝const xmlData = ref(null);
const loading = ref(false);
const error = ref("");
onMounted(async () => {
loading.value = true;
try {
const res = await fetch("/api/config.xml");
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const xmlStr = await res.text();
const doc = new DOMParser().parseFromString(xmlStr, "text/xml");
if (doc.querySelector("parsererror")) {
throw new Error("XML 格式错误");
}
xmlData.value = parseXmlToObj(doc.documentElement);
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
});多数场景不需要完整 DOM 树,只需提取关键字段。用递归容易栈溢出或陷入命名空间陷阱,推荐按需提取子节点文本和属性。
element.tagName 区分大小写,XML 是严格区分的(如 Config ≠ config)element.getAttribute("attr") 取属性,element.textContent.trim() 取文本内容element.children——注释、换行会变成 Text 节点,应过滤 nodeType === 1
function parseXmlToObj(el) {
const obj = {};
// 取所有属性
for (let i = 0; i < el.attributes.length; i++) {
const attr = el.attributes[i];
obj[`@${attr.name}`] = attr.value;
}
// 取直接子元素(忽略文本/注释)
Array.from(el.children).forEach(child => {
if (child.nodeType === 1) {
obj[child.tagName] = child.textContent.trim() || null;
}
});
return
obj;
}别把原始 XMLSerializer().serializeToString(node) 结果丢给 v-html——它不会自动转义,可能执行脚本或破坏布局。
+ XMLSerializer 更安全
highlight.js 并指定语言为 xml
zuojiankuohaophpcn)比前端拼接更可控textContent 多出换行)、命名空间未处理、以及把 XML 节点对象直接塞进响应式数据里导致无限循环或内存泄漏。