J'ai une chaîne qui représente un XML non mis en retrait que je voudrais bien imprimer. Par exemple:
<root><node/></root>
devrait devenir:
<root>
<node/>
</root>
La mise en évidence de la syntaxe n'est pas une obligation. Pour résoudre ce problème, je transforme d'abord le code XML pour ajouter des retours à la ligne et des espaces, puis j'utilise une balise pre pour afficher le XML. Pour ajouter de nouvelles lignes et des espaces, j'ai écrit la fonction suivante:
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;
}
J'appelle alors la fonction comme ceci:
jQuery('pre.formatted-xml').text(formatXml('<root><node1/></root>'));
Cela fonctionne parfaitement pour moi, mais pendant que j'écrivais la fonction précédente, j'ai pensé qu'il devait y avoir un meilleur moyen. Ma question est donc la suivante: connaissez-vous une meilleure façon, étant donné qu’une chaîne XML soit belle d’imprimer dans une page html? Tous les frameworks et/ou plugins javascript qui pourraient faire le travail sont les bienvenus. Ma seule exigence est que cela soit fait du côté client.
À partir du texte de la question , j'ai l'impression qu'un résultat sous forme de chaîne est attendu , par opposition à un résultat au format HTML.
Si tel est le cas, le moyen le plus simple d'y parvenir est de traiter le document XML avec le transformation d'identité et avec un <xsl:output indent="yes"/>
instruction :
<xsl: stylesheet version = "1.0" xmlns: xsl = "http://www.w3.org/1999/XSL/Transform"> <xsl: output omit-xml-declaration = "yes" indent = "yes" /> <xsl: template match = "node () | @ *"> <xsl: copy > <xsl: apply-templates select = "noeud () | @ *" />[____.] </ xsl: copie> </ xsl: modèle> </ xsl: stylesheet>
Lors de l'application de cette transformation sur le document XML fourni:
<root> <noeud /> </ root>
la plupart des processeurs XSLT (.NET XslCompiledTransform, Saxon 6.5.4 et Saxon 9.0.0.2, AltovaXML) produisent le résultat souhaité:
<root> <node /> </root>
envisager d'utiliser le plugin vkBeautify
http://www.eslinstructor.net/vkbeautify/
il est écrit en javascript, très petit: moins de 1,5K si minifié, très rapide: moins de 5 ms. traiter du texte XML 50K.
Légère modification de la fonction javascript de efnx clckclcks. J'ai changé la mise en forme d'espaces en tabulation, mais j'ai surtout permis au texte de rester sur une seule ligne:
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;
};
Cela peut être fait en utilisant des outils javascript natifs, sans bibliothèque tierce, en étendant la réponse de @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>'));
Les sorties:
<root>
<node/>
</root>
Personnellement, j'utilise google-code-prettify avec cette fonction:
prettyPrintOne('<root><node1><root>', 'xml')
J'ai trouvé ce fil lorsque j'avais une exigence similaire, mais j'ai simplifié le code de OP comme suit:
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);
}
travaille pour moi!
Ou si vous souhaitez simplement qu'une autre fonction js le fasse, j'ai modifié Darin (beaucoup):
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;
};
Cette bibliothèque fait exactement ce que vous voulez!
Toutes les fonctions javascript indiquées ici ne fonctionneront pas pour un document xml comportant des espaces non spécifiés entre la balise de fin ">" et la balise de début "<". Pour les corriger, il vous suffit de remplacer la première ligne dans les fonctions
var reg = /(>)(<)(\/*)/g;
par
var reg = /(>)\s*(<)(\/*)/g;
que diriez-vous de créer un nœud de stub (document.createElement ('div') - ou d’utiliser votre équivalent de bibliothèque), de le remplir avec la chaîne xml (via innerHTML) et d’appeler une fonction récursive simple pour l’élément racine/ou l’élément stub au cas où vous n'a pas de racine. La fonction s’appellera pour tous les nœuds enfants.
Vous pouvez ensuite mettre en surbrillance la syntaxe en cours de route, en vous assurant que le balisage est bien formé (effectué automatiquement par le navigateur lors de l'ajout via innerHTML), etc.
Si vous recherchez une solution JavaScript, prenez simplement le code de l'outil Pretty Diff à l'adresse http://prettydiff.com/?m=beautify .
Vous pouvez également envoyer des fichiers à l'outil à l'aide du paramètre s, tels que: http://prettydiff.com/?m=beautify&s=https://stackoverflow.com/
Vous pouvez obtenir un joli XML formaté avec xml-beautify
var prettyXmlText = new XmlBeautify().beautify(xmlText,
{indent: " ",useSelfClosingElement: true});
indent : motif d'indentation comme des espaces blancs
useSelfClosingElement : true => utilise un élément à fermeture automatique lorsqu'un élément est vide.
Original (avant)
<?xml version="1.0" encoding="utf-8"?><example version="2.0">
<head><title>Original aTitle</title></head>
<body info="none" ></body>
</example>
Embellie (après)
<?xml version="1.0" encoding="utf-8"?>
<example version="2.0">
<head>
<title>Original aTitle</title>
</head>
<body info="none" />
</example>
Or just print out the special HTML characters?
Ex: <xmlstuff> 	<node /> </xmlstuff>
	 Horizontal tab
Line feed
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';
XMLSpectrum formate XML, prend en charge l'indentation des attributs et met également en surbrillance la syntaxe pour XML et toutes les expressions XPath incorporées:
XMLSpectrum est un projet open source, codé en XSLT 2.0 - vous pouvez donc l'exécuter côté serveur avec un processeur tel que Saxon-HE (recommandé) ou côté client à l'aide de Saxon-CE.
XMLSpectrum n'est pas encore optimisé pour s'exécuter dans le navigateur - d'où la recommandation d'exécuter ce côté serveur.
voici une autre fonction pour formater 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;
}
Utilisez la méthode ci-dessus pour de jolies impressions, puis ajoutez-la à n’importe quelle div en utilisant jquery text () method. Par exemple, id de div est xmldiv
, puis utilisez:
$("#xmldiv").text(formatXml(youXmlString));
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
Cette bibliothèque fonctionne pour moi. Prise en charge de l'onglet, prise en charge de la version Web et du nœud. Prend également en charge JS, HTML, CSS. Aussi disponible en CDN.