📑 XML 格式化

XML 格式化与压缩,支持属性、CDATA、注释、命名空间。可自定义缩进。

等待输入...
已复制
const SAMPLE = 'BobHello\ntext]]>2025-01-01'; function formatXml(xml, indent){ const doc = new DOMParser().parseFromString(xml, 'application/xml'); if(doc.getElementsByTagName('parsererror').length) throw new Error('XML 解析错误'); return serializeNode(doc.documentElement, 0, indent); } function serializeNode(node, depth, indent){ const pad = indent ? ' '.repeat(depth) : ''; let s = ''; for(const child of node.childNodes){ if(child.nodeType === 1){ const tag = child.tagName; const attrs = Array.from(child.attributes).map(a => a.name + '="' + escAttr(a.value) + '"').join(' '); const open = '<' + tag + (attrs ? ' ' + attrs : ''); const kids = Array.from(child.childNodes).filter(c => c.nodeType === 1 || (c.nodeType === 3 && c.textContent.trim())); if(kids.length === 0){ s += pad + open + '/>'; } else if(kids.length === 1 && kids[0].nodeType === 3){ s += pad + open + '>' + escXml(kids[0].textContent) + ''; } else { s += pad + open + '>'; if(indent) s += '\n'; s += serializeNode(child, depth + 1, indent); s += pad + ''; } if(indent) s += '\n'; } else if(child.nodeType === 4){ s += pad + ''; if(indent) s += '\n'; } else if(child.nodeType === 8){ s += pad + ''; if(indent) s += '\n'; } else if(child.nodeType === 3 && child.textContent.trim()){ s += pad + escXml(child.textContent.trim()); if(indent) s += '\n'; } } return s; } function escXml(s){ return String(s).replace(/&/g,'&').replace(//g,'>'); } function escAttr(s){ return escXml(s).replace(/"/g,'"'); } function doBeautify(){ setErr(''); try{ setOut(formatXml(document.getElementById('input').value, true)); setErr('✅ 格式化成功'); }catch(e){ setErr('❌ ' + e.message); } } function doMinify(){ setErr(''); try{ setOut(formatXml(document.getElementById('input').value, false).replace(/\n/g,'')); setErr('✅ 压缩成功'); }catch(e){ setErr('❌ ' + e.message); } } function doValidate(){ setErr(''); try{ const doc = new DOMParser().parseFromString(document.getElementById('input').value, 'application/xml'); if(doc.getElementsByTagName('parsererror').length) throw new Error('XML 解析错误'); const root = doc.documentElement; setErr('✅ 有效 XML,根元素 <' + root.tagName + '>,子节点数 ' + root.children.length); setOut(formatXml(document.getElementById('input').value, true)); }catch(e){ setErr('❌ ' + e.message); } } function loadSample(){document.getElementById('input').value = SAMPLE; doBeautify();} function getIndent(){const v=document.getElementById('indent').value;return v==='tab'?'\t':' '.repeat(parseInt(v));} function setOut(s){document.getElementById('output').textContent=s;} function setErr(s){const e=document.getElementById('err');e.textContent=s||'';e.className='err'+(s?'':' ok');} function clearAll(){document.getElementById('input').value='';setOut('等待输入...');setErr('');} function loadSample(){document.getElementById('input').value=SAMPLE;doBeautify();}