Pretty XML di stampa con javascript

Ho una stringa che rappresenta un XML non indentato che mi piacerebbe stampare piuttosto. Per esempio:

 

dovrebbe diventare:

    

L’evidenziazione della syntax non è un requisito. Per affrontare il problema, prima trasformo l’XML per aggiungere ritorni a capo e spazi bianchi e quindi utilizzare un tag pre per emettere l’XML. Per aggiungere nuove linee e spazi bianchi ho scritto la seguente funzione:

 function formatXml(xml) { var formatted = ''; var reg = /(>)(<)(\/*)/g; xml = xml.replace(reg, '$1\r\n$2$3'); var pad = 0; jQuery.each(xml.split('\r\n'), function(index, node) { var indent = 0; if (node.match( /.+]*>$/ )) { indent = 0; } else if (node.match( /^<\/\w/ )) { if (pad != 0) { pad -= 1; } } else if (node.match( /^]*[^\/]>.*$/ )) { indent = 1; } else { indent = 0; } var padding = ''; for (var i = 0; i < pad; i++) { padding += ' '; } formatted += padding + node + '\r\n'; pad += indent; }); return formatted; } 

Quindi chiamo la funzione in questo modo:

 jQuery('pre.formatted-xml').text(formatXml('')); 

Questo funziona perfettamente bene per me, ma mentre stavo scrivendo la funzione precedente ho pensato che ci doveva essere un modo migliore. Quindi la mia domanda è che sapete di un modo migliore dato una stringa XML per stampare piuttosto in una pagina HTML? Qualsiasi framework javascript e / o plugin che potrebbero fare il lavoro sono i benvenuti. Il mio unico requisito è che ciò avvenga sul lato client.

Dal testo della domanda ho l’impressione che sia previsto un risultato di stringa , al contrario di un risultato in formato HTML.

Se è così, il modo più semplice per ottenere ciò è elaborare il documento XML con la trasformazione dell’identity framework e con un’istruzione :

 
  

     
       
         
       
     
 

Quando si applica questa trasformazione sul documento XML fornito:

   

la maggior parte dei processori XSLT (.NET XslCompiledTransform, Saxon 6.5.4 e Saxon 9.0.0.2, AltovaXML) producono il risultato desiderato:

 
   
 

considera di usare il plugin vkBeautify

http://www.eslinstructor.net/vkbeautify/

è scritto in javascript semplice, molto piccolo: meno di 1.5K se minificato, molto veloce: meno di 5 msec. per elaborare il testo XML 50K.

Leggera modifica della funzione javascript di efnx clckclcks. Ho modificato la formattazione da spazi a tab, ma soprattutto ho lasciato che il testo rimanesse su una riga:

 var formatXml = this.formatXml = function (xml) { var reg = /(>)\s*(< )(\/*)/g; // updated Mar 30, 2015 var wsexp = / *(.*) +\n/g; var contexp = /(<.+>)(.+\n)/g; xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); var pad = 0; var formatted = ''; var lines = xml.split('\n'); var indent = 0; var lastType = 'other'; // 4 types of tags - single, closing, opening, other (text, doctype, comment) - 4*4 = 16 transitions var transitions = { 'single->single': 0, 'single->closing': -1, 'single->opening': 0, 'single->other': 0, 'closing->single': 0, 'closing->closing': -1, 'closing->opening': 0, 'closing->other': 0, 'opening->single': 1, 'opening->closing': 0, 'opening->opening': 1, 'opening->other': 1, 'other->single': 0, 'other->closing': -1, 'other->opening': 0, 'other->other': 0 }; for (var i = 0; i < lines.length; i++) { var ln = lines[i]; // Luca Viggiani 2017-07-03: handle optional  declaration if (ln.match(/\s*< \?xml/)) { formatted += ln + "\n"; continue; } // --- var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. 
var closing = Boolean(ln.match(/< \/.+>/)); // is this a closing tag? ex. var opening = Boolean(ln.match(/< [^!].*>/)); // is this even a tag (that's not < !something>) var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other'; var fromTo = lastType + '->' + type; lastType = type; var padding = ''; indent += transitions[fromTo]; for (var j = 0; j < indent; j++) { padding += '\t'; } if (fromTo == 'opening->closing') formatted = formatted.substr(0, formatted.length - 1) + ln + '\n'; // substr removes line break (\n) from prev loop else formatted += padding + ln + '\n'; } return formatted; };

Personnaly, io uso google-code-prettify con questa funzione:

 prettyPrintOne('', 'xml') 

O se ti piacerebbe avere un’altra funzione js per farlo, ho modificato Darin (molto):

 var formatXml = this.formatXml = function (xml) { var reg = /(>)(< )(\/*)/g; var wsexp = / *(.*) +\n/g; var contexp = /(<.+>)(.+\n)/g; xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); var pad = 0; var formatted = ''; var lines = xml.split('\n'); var indent = 0; var lastType = 'other'; // 4 types of tags - single, closing, opening, other (text, doctype, comment) - 4*4 = 16 transitions var transitions = { 'single->single' : 0, 'single->closing' : -1, 'single->opening' : 0, 'single->other' : 0, 'closing->single' : 0, 'closing->closing' : -1, 'closing->opening' : 0, 'closing->other' : 0, 'opening->single' : 1, 'opening->closing' : 0, 'opening->opening' : 1, 'opening->other' : 1, 'other->single' : 0, 'other->closing' : -1, 'other->opening' : 0, 'other->other' : 0 }; for (var i=0; i < lines.length; i++) { var ln = lines[i]; var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. 
var closing = Boolean(ln.match(/< \/.+>/)); // is this a closing tag? ex. var opening = Boolean(ln.match(/< [^!].*>/)); // is this even a tag (that's not < !something>) var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other'; var fromTo = lastType + '->' + type; lastType = type; var padding = ''; indent += transitions[fromTo]; for (var j = 0; j < indent; j++) { padding += ' '; } formatted += padding + ln + '\n'; } return formatted; };

Questo può essere fatto usando strumenti javascript nativi, senza librerie di terze parti, estendendo la risposta di @Dimitre Novatchev:

 var prettifyXml = function(sourceXml) { var xmlDoc = new DOMParser().parseFromString(sourceXml, 'application/xml'); var xsltDoc = new DOMParser().parseFromString([ // describes how we want to modify the XML - indent everything '', ' ', ' ', // change to just text() to strip space in text nodes ' ', ' ', ' ', ' ', ' ', ' ', '', ].join('\n'), 'application/xml'); var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xsltDoc); var resultDoc = xsltProcessor.transformToDocument(xmlDoc); var resultXml = new XMLSerializer().serializeToString(resultDoc); return resultXml; }; console.log(prettifyXml('')); 

Uscite:

    

JSFiddle

Tutte le funzioni javascript fornite qui non funzioneranno per un documento xml con spazi bianchi non specificati tra il tag di chiusura ‘>’ e il tag di inizio ‘< '. Per risolverli, è sufficiente sostituire la prima riga nelle funzioni

 var reg = /(>)(< )(\/*)/g; 

di

 var reg = /(>)\s*(< )(\/*)/g; 

Questa libreria fa esattamente quello che vuoi!

https://code.google.com/p/vkbeautify/

per quanto riguarda la creazione di un nodo stub (document.createElement (‘div’) – o l’equivalente della libreria), riempiendolo con la stringa xml (tramite innerHTML) e chiamando la funzione ricorsiva semplice per l’elemento root / o l’elemento stub nel caso tu non avere una radice. La funzione si chiamerebbe per tutti i nodes figlio.

Potresti quindi syntax-evidenziare lungo la strada, assicurati che il markup sia ben formato (fatto automaticamente dal browser quando si aggiunge tramite innerHTML), ecc. Non sarebbe tanto codice e probabilmente abbastanza veloce.

Se stai cercando una soluzione JavaScript, prendi il codice dallo strumento Pretty Diff su http://prettydiff.com/?m=beautify

È inoltre ansible inviare file allo strumento utilizzando il parametro s, ad esempio: http://prettydiff.com/?m=beautify&s=https://stackoverflow.com/

Trovato questo thread quando ho avuto un requisito simile ma ho semplificato il codice OP come segue:

 function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t) var formatted = '', indent= ''; tab = tab || '\t'; xml.split(/>\s*\r\n'; if (node.match( /^< ?\w[^>]*[^\/]$/ )) indent += tab; // increase indent }); return formatted.substring(1, formatted.length-3); } 

per me va bene!

 var formatXml = this.formatXml = function (xml) { var reg = /(>)(< )(\/*)/g; var wsexp = / *(.*) +\n/g; var contexp = /(<.+>)(.+\n)/g; xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); var pad = 0; var formatted = ''; var lines = xml.split('\n'); var indent = 0; var lastType = 'other'; 
 Or just print out the special HTML characters? Ex: 
 	
 	 Horizontal tab 
 Line feed 

XMLSpectrum formati XML, supporta l’indentazione degli attributi e fa anche l’evidenziazione della syntax per XML e qualsiasi espressione XPath incorporata:

XMLSpectrum XML formattato

XMLSpectrum è un progetto open source, codificato in XSLT 2.0, quindi puoi eseguire questo lato server con un processore come Saxon-HE (consigliato) o lato client usando Saxon-CE.

XMLSpectrum non è ancora ottimizzato per l’esecuzione nel browser, da cui la raccomandazione di eseguire questo lato server.

Usa il metodo sopra per una bella stampa e aggiungilo in qualsiasi div usando il metodo jquery text () . per esempio id di div è xmldiv quindi usa:

$("#xmldiv").text(formatXml(youXmlString));

ecco un’altra funzione per formattare xml

 function formatXml(xml){ var out = ""; var tab = " "; var indent = 0; var inClosingTag=false; var dent=function(no){ out += "\n"; for(var i=0; i < no; i++) out+=tab; } for (var i=0; i < xml.length; i++) { var c = xml.charAt(i); if(c=='<'){ // handle '){ out+=c; // handle /> if(xml.charAt(i-1) == '/'){ out+="\n"; //dent(--indent) }else{ if(!inClosingTag) dent(++indent); else{ out+="\n"; inClosingTag=false; } } }else{ out+=c; } } return out; } 
 var reg = /(>)\s*(< )(\/*)/g; xml = xml.replace(/\r|\n/g, ''); //deleting already existing whitespaces xml = xml.replace(reg, '$1\r\n$2$3'); 

https://www.npmjs.com/package/js-beautify

Questa libreria funziona per me. Supporta la scheda, supporta la versione web e del nodo. Supporta anche JS, HTML, CSS. Disponibile anche come CDN.

È ansible ottenere xml piuttosto formattato con xml-beautify

 var prettyXmlText = new XmlBeautify().beautify(xmlText, {indent: " ",useSelfClosingElement: true}); 

rientro : modello di rientro come spazi bianchi

useSelfClosingElement : true => usa l’elemento self-closing quando vuoto elemento.

JSFiddle

Originale (Prima)

 < ?xml version="1.0" encoding="utf-8"?> Original aTitle   

Abbellito (After)

 < ?xml version="1.0" encoding="utf-8"?>   Original aTitle