很好用javascript打印XML

我有一个string,表示一个非缩进的XML,我想漂亮的打印。 例如:

<root><node/></root> 

应该成为:

 <root> <node/> </root> 

语法突出显示不是必需的。 为了解决这个问题,我首先转换XML来添加回车符和空格,然后使用pre标签输出XML。 为了添加新的行和空格,我写了下面的函数:

 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; } 

然后我调用这个函数:

 jQuery('pre.formatted-xml').text(formatXml('<root><node1/></root>')); 

这对我来说工作得很好,但是在我写前面的函数的时候,我认为必须有一个更好的方法。 所以我的问题是你知道任何更好的方式给一个XMLstring漂亮的打印在一个HTML页面? 任何可以完成这个工作的javascript框架和/或插件都是受欢迎的。 我唯一的要求是在客户端完成。

从问题的文本中, 我得到的结果是一个string结果的预期 ,而不是一个HTML格式的结果。

如果是这样的话, 最简单的方法是使用标识转换和<xsl:output indent="yes"/>指令来处理XML文档

 <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:拷贝>
         <xsl:apply-templates select =“node()| @ *”/>
       </ XSL:复制>
     </ XSL:模板>
 </ XSL:样式>

在提供的XML文档上应用此转换时:

 <根> <节点/> </根>

大多数XSLT处理器(.NET XslCompiledTransform,Saxon 6.5.4和Saxon 9.0.0.2,AltovaXML)都会产生所需的结果:

 <根>
   <node />
 </根>

考虑使用vkBeautify插件

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

它是用普通的javascript编写的,非常小:小于1.5K,非常快,小于5毫秒。 处理50K XML文本。

对efnx clckclcks的javascript函数稍作修改。 我将格式从空格改为了tab,但最重要的是我允许文本保持在一行:

 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; }; 

Personnaly,我用这个函数使用google-code-prettify :

 prettyPrintOne('<root><node1><root>', 'xml') 

或者如果你只是想另一个js函数去做,我已经修改了Darin(很多):

 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; }; 

所有这里给出的javascript函数将不适用于在结束标记“>”和开始标记“<”之间具有未指定空格的xml文档。 要解决它们,只需要replace函数中的第一行

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

通过

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

这个库完全是你想要的!

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

如何创build一个存根节点(document.createElement('div') – 或者使用你的库等价物),用xmlstring填充(通过innerHTML),并为根元素/或存根元素调用简单的recursion函数没有根。 该函数将自行调用所有的子节点。

然后你可以沿着语法突出显示,确定标记是正确的(当通过innerHTML附加时由浏览器自动完成)等。这不会是那么多的代码,可能不够快。

如果您正在寻找JavaScript解决scheme,只需从http://prettydiff.com/?m=beautify上的Pretty Diff工具中获取代码

您也可以使用s参数将文件发送到该工具,例如: http : //prettydiff.com/? m= beautify& s= https : //stackoverflow.com/

这里是另一个格式化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; } 
 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: <xmlstuff>&#10; &#09;<node />&#10;</xmlstuff> &#09; Horizontal tab &#10; Line feed 

XMLSpectrum格式化XML,支持属性缩进,并为XML和任何embedded式XPathexpression式进行语法高亮显示:

XMLSpectrum格式化的XML

XMLSpectrum是一个开源项目,使用XSLT 2.0编码 – 所以您可以使用Saxon-CE等处理器(如Saxon-HE(推荐)或客户端)运行此服务器端。

XMLSpectrum尚未优化在浏览器中运行 – 因此build议运行此服务器端。

使用上面的方法进行漂亮的打印,然后通过使用jquery text()方法将其添加到任何div中。 例如div的id是xmldiv然后使用:

$("#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

这个库为我工作。 支持选项卡,支持Web和节点版本。 还支持JS,HTML,CSS。 也可作为CDN。

这可以使用本地JavaScript工具,没有第三方库,扩展@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:output omit-xml-declaration="yes" indent="yes"/>', ' <xsl:template match="node()|@*">', ' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>', ' </xsl:template>', '</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>')); 

输出:

 <root> <node/> </root> 

的jsfiddle