(function(){
function qs(sel,root){return(root||document).querySelector(sel)}
var root=document.getElementById('sd-xmlfmt');if(!root)return;
var el={
input:qs('#sdxf-input',root),
output:qs('#sdxf-output',root),
error:qs('#sdxf-error',root),
indent:qs('#sdxf-indent',root),
sortAttrs:qs('#sdxf-sort-attrs',root),
sortElems:qs('#sdxf-sort-elems',root),
btnFmt:qs('#sdxf-format',root),
btnMin:qs('#sdxf-minify',root),
btnCopy:qs('#sdxf-copy',root),
btnDl:qs('#sdxf-download',root),
btnClr:qs('#sdxf-clear',root)
};
function showError(m){el.error.textContent=m;el.error.hidden=false}
function clearError(){el.error.hidden=true;el.error.textContent=''}
function getIndent(){
var v=el.indent.value;
if(v==="\\t"||v==="\t")return"\t";
if(isNaN(v))return v;
return new Array(parseInt(v,10)+1).join(" ");
}
function parseXML(str){
var parser=new DOMParser();
var doc=parser.parseFromString(str,"application/xml");
var err=doc.getElementsByTagName("parsererror")[0];
if(err){return{doc:null,error:err.textContent.replace(/\s+/g,' ').trim()}}
return{doc:doc,error:null};
}
function sortAttributes(node){
if(node.nodeType===1&&node.attributes&&node.attributes.length>1){
var arr=[],i;
for(i=0;i<node.attributes.length;i++){arr.push({n:node.attributes[i].name,v:node.attributes[i].value})}
arr.sort(function(a,b){return a.n.localeCompare(b.n,undefined,{numeric:true,sensitivity:'base'})});
while(node.attributes.length){node.removeAttribute(node.attributes[0].name)}
for(i=0;i1){
elems.sort(function(a,b){
var t=a.tagName.localeCompare(b.tagName,undefined,{numeric:true,sensitivity:'base'});
if(t!==0)return t;
var ai=a.getAttribute('id')||a.getAttribute('name')||'';
var bi=b.getAttribute('id')||b.getAttribute('name')||'';
return ai.localeCompare(bi,undefined,{numeric:true,sensitivity:'base'});
});
for(var i=0;i<elems.length;i++){node.appendChild(elems[i])}
}
for(var j=0;j<children.length;j++){sortElements(children[j])}
}
function escapeText(s){return s.replace(/&/g,'&').replace(//g,'>')}
function escapeAttr(s){return s.replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<')}
function prettyPrint(node,IND,level){
var out='';
if(node.nodeType===9){
for(var ch=node.firstChild;ch;ch=ch.nextSibling){out+=prettyPrint(ch,IND,0)}
return out;
}
if(node.nodeType===1){
var name=node.nodeName,attrs='',i;
for(i=0;i0&&children.every?children.every(function(n){return n.nodeType===3})
:children.filter(function(n){return n.nodeType!==3}).length===0;
var pad=new Array(level+1).join(IND);
if(selfClosing){out+=pad+'\n'}
else if(onlyText){
var text=children.map?children.map(function(c){return c.nodeValue}).join(''):node.textContent;
out+=pad+''+escapeText(String(text).trim())+''+name+'>\n';
}else{
out+=pad+'\n';
for(i=0;i<children.length;i++){out+=prettyPrint(children[i],IND,level+1)}
out+=pad+''+name+'>\n';
}
return out;
}
if(node.nodeType===3){
var v=String(node.nodeValue).replace(/\s+/g,' ').trim();
if(v){out+=new Array(level+1).join(IND)+escapeText(v)+'\n'}
return out;
}
if(node.nodeType===4){return new Array(level+1).join(IND)+'\n'}
if(node.nodeType===8){return new Array(level+1).join(IND)+'\n'}
if(node.nodeType===7){return new Array(level+1).join(IND)+'\n'}
return out;
}
function minifyXML(doc){
var s=new XMLSerializer();
return s.serializeToString(doc).replace(/>\s+<').trim();
}
function highlight(xml){
var esc=xml.replace(/&/g,'&').replace(//g,'>');
esc=esc.replace(/<!--([\s\S]*?)-->/g,function(_,a){return'<!--'+a+'-->'});
esc=esc.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g,function(_,a){return'<![CDATA['+a+']]>'});
esc=esc.replace(/<(\/?)([a-zA-Z_:][\w:.-]*)([^&]*?)(\s*\/?)>/g,function(_,slash,tag,rest,selfClose){
var attrs=rest.replace(/([a-zA-Z_:][\w:.-]*)(\s*=\s*)(".*?"|'.*?')/g,
function(__,an,eq,av){return' '+an+''+eq+''+av+''}
);
return'<'+slash+''+tag+''+attrs+selfClose+'>';
});
esc=esc.replace(/(^|[^;])&([a-zA-Z#0-9]+);/g,function(_,b1,ent){return b1+'&'+ent+';'});
return esc;
}
function formatXML(minify){
clearError();
var raw=el.input.value.replace(/^\uFEFF/,'').trim();
if(!raw){el.output.innerHTML='';return}
var parsed=parseXML(raw);
if(parsed.error){showError('XML-Fehler: '+parsed.error);return}
try{
if(el.sortAttrs.checked)sortAttributes(parsed.doc);
if(el.sortElems.checked)sortElements(parsed.doc);
var result=minify?minifyXML(parsed.doc):prettyPrint(parsed.doc,getIndent(),0).trim();
el.output.innerHTML=highlight(result);
}catch(e){
showError('Verarbeitung fehlgeschlagen: '+(e&&e.message?e.message:e));
}
}
el.btnFmt.addEventListener('click',function(){formatXML(false)});
el.btnMin.addEventListener('click',function(){formatXML(true)});
el.btnCopy.addEventListener('click',function(){
if(navigator.clipboard){navigator.clipboard.writeText(el.output.innerText);return}
var t=document.createElement('textarea');t.value=el.output.innerText;
document.body.appendChild(t);t.select();document.execCommand('copy');t.remove();
});
el.btnDl.addEventListener('click',function(){
var text=el.output.innerText||'';
var blob=new Blob([text],{type:'application/xml;charset=utf-8'});
var a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='formatted.xml';
document.body.appendChild(a);a.click();a.remove();URL.revokeObjectURL(a.href);
});
el.btnClr.addEventListener('click',function(){el.input.value='';el.output.innerHTML='';clearError()});
el.input.addEventListener('input',function(){
clearError();
var v=el.input.value.trim();if(!v)return;
var res=parseXML(v);if(res.error)showError('Noch ungültig: '+res.error);
});
el.input.addEventListener('keydown',function(ev){
if((ev.ctrlKey||ev.metaKey)&&ev.key==='Enter')formatXML(false);
});
})();
XML begegnet einem selten zum Spaß – meist steckt ein Datenaustausch zwischen zwei Systemen dahinter: Warenwirtschaft, ERP oder Versanddienstleister. Soll dieser Austausch automatisch und zuverlässig laufen statt per Copy-and-paste, übernimmt SERVIT die Schnittstellen- und ERP-Anbindung für Sie.
Mit dem XML Formatter strukturierst du XML in Sekunden: Einrückung wählen, Attribute optional alphabetisch sortieren, sauber formatiert anzeigen oder komprimieren (Minify). Fehler werden sofort erkannt und im Tool angezeigt. Kopieren und Download sind mit einem Klick möglich. Datenschutz: Alles läuft ausschließlich im Browser. Keine Speicherung, keine Server-Übertragung – ideal auch für vertrauliche Daten.
Funktionen im Überblick
XML formatieren mit wählbarer Einrückung (2/4 Spaces, Tab)
Optional: Attribute alphabetisch sortieren
Minify (kompakte Ausgabe)
Live-Fehlerprüfung bei ungültigem XML
Inhalt kopieren oder als Datei herunterladen
100 % lokal – keine Datenübertragung, keine Speicherung