Saya memiliki string yang mewakili XML tanpa indentasi yang ingin saya cetak dengan cantik. Sebagai contoh:
<root><node/></root>
harus menjadi:
<root>
<node/>
</root>
Penyorotan sintaks bukan persyaratan. Untuk mengatasi masalah ini saya pertama-tama mengubah XML untuk menambahkan carriage return dan spasi dan kemudian menggunakan tag pra untuk mengeluarkan XML. Untuk menambahkan baris baru dan spasi saya menulis fungsi berikut:
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( /.+<\/\w[^>]*>$/ )) {
indent = 0;
} else if (node.match( /^<\/\w/ )) {
if (pad != 0) {
pad -= 1;
}
} else if (node.match( /^<\w[^>]*[^\/]>.*$/ )) {
indent = 1;
} else {
indent = 0;
}
var padding = '';
for (var i = 0; i < pad; i++) {
padding += ' ';
}
formatted += padding + node + '\r\n';
pad += indent;
});
return formatted;
}
Saya kemudian memanggil fungsi seperti ini:
jQuery('pre.formatted-xml').text(formatXml('<root><node1/></root>'));
Ini berfungsi dengan baik bagi saya tetapi ketika saya menulis fungsi sebelumnya, saya pikir pasti ada cara yang lebih baik. Jadi pertanyaan saya adalah apakah Anda mengetahui cara yang lebih baik untuk memberikan string XML untuk mencetaknya dengan cantik di halaman html? Kerangka kerja javascript dan / atau plugin apa pun yang dapat melakukan pekerjaan itu dipersilakan. Satu-satunya persyaratan saya adalah ini dilakukan di sisi klien.
sumber
Jawaban:
Dari teks pertanyaan saya mendapat kesan bahwa hasil string diharapkan , bukan hasil dalam format HTML.
Jika demikian, cara termudah untuk mencapai ini adalah dengan memproses dokumen XML dengan transformasi identitas dan dengan
<xsl:output indent="yes"/>
instruksi :Saat menerapkan transformasi ini pada dokumen XML yang disediakan:
sebagian besar prosesor XSLT (.NET XslCompiledTransform, Saxon 6.5.4 dan Saxon 9.0.0.2, AltovaXML) menghasilkan hasil yang diinginkan:
sumber
Ini dapat dilakukan dengan menggunakan alat javascript asli, tanpa libs pihak ketiga, memperluas jawaban @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 '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">', ' <xsl:strip-space elements="*"/>', ' <xsl:template match="para[content-style][not(text())]">', // change to just text() to strip space in text nodes ' <xsl:value-of select="normalize-space(.)"/>', ' </xsl:template>', ' <xsl:template match="node()|@*">', ' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>', ' </xsl:template>', ' <xsl:output indent="yes"/>', '</xsl:stylesheet>', ].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('<root><node/></root>'));
Keluaran:
<root> <node/> </root>
JSFiddle
Catatan, seperti yang ditunjukkan oleh @ jat255, pencetakan cantik dengan
<xsl:output indent="yes"/>
tidak didukung oleh firefox. Sepertinya hanya berfungsi di chrome, opera, dan mungkin browser berbasis webkit lainnya.sumber
private makeSingleLine(txt: string): string { let s = txt.trim().replace(new RegExp("\r", "g"), "\n"); let angles = ["<", ">"]; let empty = [" ", "\t", "\n"]; while (s.includes(" <") || s.includes("\t<") || s.includes("\n<") || s.includes("> ") || s.includes(">\t") || s.includes(">/n")) { angles.forEach(an => { empty.forEach(em => { s = s.replace(new RegExp(em + an, "g"), an); }); }); } return s.replace(new RegExp("\n", "g"), " "); }
xsl:output
tag apa pun , jadi Anda tidak akan mendapatkan yang terbaik. memformat.Sedikit modifikasi dari fungsi javascript efnx clckclcks. Saya mengubah pemformatan dari spasi ke tab, tetapi yang paling penting saya mengizinkan teks tetap dalam satu baris:
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 <?xml ... ?> declaration if (ln.match(/\s*<\?xml/)) { formatted += ln + "\n"; continue; } // --- var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. <br /> var closing = Boolean(ln.match(/<\/.+>/)); // is this a closing tag? ex. </a> 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; };
sumber
<?xml ... ?>
deklarasi opsional di awal teks XMLMenemukan utas ini ketika saya memiliki persyaratan serupa tetapi saya menyederhanakan kode OP sebagai berikut:
function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t) var formatted = '', indent= ''; tab = tab || '\t'; xml.split(/>\s*</).forEach(function(node) { if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab' formatted += indent + '<' + node + '>\r\n'; if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent }); return formatted.substring(1, formatted.length-3); }
bekerja untuk saya!
sumber
Secara pribadi, saya menggunakan google-code-prettify dengan fungsi ini:
prettyPrintOne('<root><node1><root>', 'xml')
sumber
Atau jika Anda hanya ingin fungsi js lain melakukannya, saya telah memodifikasi Darin's (banyak):
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. <br /> var closing = Boolean(ln.match(/<\/.+>/)); // is this a closing tag? ex. </a> 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; };
sumber
Semua fungsi javascript yang diberikan di sini tidak akan berfungsi untuk dokumen xml yang memiliki spasi kosong yang tidak ditentukan antara tag akhir '>' dan tag awal '<'. Untuk memperbaikinya, Anda hanya perlu mengganti baris pertama di fungsi
var reg = /(>)(<)(\/*)/g;
oleh
var reg = /(>)\s*(<)(\/*)/g;
sumber
bagaimana dengan membuat simpul rintisan (document.createElement ('div') - atau menggunakan perpustakaan Anda yang setara), mengisinya dengan string xml (melalui innerHTML) dan memanggil fungsi rekursif sederhana untuk elemen root / atau elemen rintisan jika Anda tidak memiliki root. Fungsi tersebut akan memanggil dirinya sendiri untuk semua node turunan.
Anda kemudian dapat menyorot sintaks di sepanjang jalan, memastikan markup terbentuk dengan baik (dilakukan secara otomatis oleh browser saat menambahkan melalui innerHTML) dll. Tidak akan banyak kode dan mungkin cukup cepat.
sumber
Jika Anda mencari solusi JavaScript, ambil saja kode dari alat Pretty Diff di http://prettydiff.com/?m=beautify
Anda juga dapat mengirim file ke alat menggunakan parameter s, seperti: http://prettydiff.com/?m=beautify&s=https://stackoverflow.com/
sumber
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';
sumber
Or just print out the special HTML characters? Ex: <xmlstuff> 	<node /> </xmlstuff> 	 Horizontal tab Line feed
sumber
XMLSpectrum memformat XML, mendukung indentasi atribut dan juga melakukan penyorotan sintaks untuk XML dan ekspresi XPath yang disematkan:
XMLSpectrum adalah proyek sumber terbuka, dengan kode XSLT 2.0 - sehingga Anda dapat menjalankan sisi server ini dengan prosesor seperti Saxon-HE (disarankan) atau sisi klien menggunakan Saxon-CE.
XMLSpectrum belum dioptimalkan untuk dijalankan di browser - karenanya direkomendasikan untuk menjalankan sisi server ini.
sumber
berikut adalah fungsi lain untuk memformat 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 </ if(xml.charAt(i+1) == '/'){ inClosingTag = true; dent(--indent); } out+=c; }else if(c=='>'){ 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; }
sumber
Anda bisa mendapatkan xml dengan format cantik dengan xml-beautify
var prettyXmlText = new XmlBeautify().beautify(xmlText, {indent: " ",useSelfClosingElement: true});
indentasi : pola indentasi seperti spasi
useSelfClosingElement : true => menggunakan elemen menutup sendiri saat elemen kosong.
JSFiddle
Asli (Sebelum)
<?xml version="1.0" encoding="utf-8"?><example version="2.0"> <head><title>Original aTitle</title></head> <body info="none" ></body> </example>
Beautified (Setelah)
<?xml version="1.0" encoding="utf-8"?> <example version="2.0"> <head> <title>Original aTitle</title> </head> <body info="none" /> </example>
sumber
var reg = /(>)\s*(<)(\/*)/g; xml = xml.replace(/\r|\n/g, ''); //deleting already existing whitespaces xml = xml.replace(reg, '$1\r\n$2$3');
sumber
Gunakan metode di atas untuk pretty print dan kemudian tambahkan ini di div apa pun dengan menggunakan metode jquery text () . misalnya id dari div
xmldiv
kemudian digunakan:$("#xmldiv").text(formatXml(youXmlString));
sumber
Ini versi saya, mungkin berguna untuk orang lain, menggunakan String builder Saw bahwa seseorang memiliki bagian kode yang sama.
public String FormatXml(String xml, String tab) { var sb = new StringBuilder(); int indent = 0; // find all elements foreach (string node in Regex.Split(xml,@">\s*<")) { // if at end, lower indent if (Regex.IsMatch(node, @"^\/\w")) indent--; sb.AppendLine(String.Format("{0}<{1}>", string.Concat(Enumerable.Repeat(tab, indent).ToArray()), node)); // if at start, increase indent if (Regex.IsMatch(node, @"^<?\w[^>]*[^\/]$")) indent++; } // correct first < and last > from the output String result = sb.ToString().Substring(1); return result.Remove(result.Length - Environment.NewLine.Length-1); }
sumber
Library Xml-to-json memiliki metode
formatXml(xml).
Saya adalah pengelola proyek.var prettyXml = formatXml("<a><b/></a>"); // <a> // <b/> // </a>
sumber