How to print pretty xml in javascript?
Asked Answered
R

6

6

What's the best way to pretty-print xml in JavaScript? I obtain xml content through ajax call and before displaying this request in textarea i want to format it so it looks nice to the eye :)

Romanticism answered 27/7, 2009 at 10:22 Comment(2)
Making XML look nice to the eye would be a magic trick!Camiecamila
In my opinion the canonical SO thread regarding this problem is pretty printing xml with javascriptLanding
C
7

This does not take care of any indenting, but helps to encode the XML for use within <pre> or <textarea> tags:

/* hack to encode HTML entities */
var d = document.createElement('div'); 
var t = document.createTextNode(myXml); 
d.appendChild(t);
document.write('<pre>' + d.innerHTML + '</pre>');

And if, instead of a <textarea>, you'd want highlighting and the nodes to be collapsable/expandable, then see Displaying XML in Chrome Browser on Super User.

Costive answered 27/7, 2009 at 11:34 Comment(0)
S
6

take a look at the vkBeautify.js plugin

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

it is exactly what you need. it's written in plain javascript, less then 1.5K minified and very fast: takes less then 5 msec. to process 50K XML text.

Stomodaeum answered 19/1, 2012 at 6:33 Comment(4)
You should publish this to npm as a proper module - would love to use it.Stonework
it is on npm: github.com/vkiryukhin/pretty-data; see documentation on eslinstructor.net/pretty-dataStomodaeum
does this support tabs?Cocke
sorry, not sure I understand this question, could you please clarify?Stomodaeum
C
4

Here is a small self contained prettifier that works for most cases does nice indenting for long lines and colorizes the output if needed.

function formatXml(xml,colorize,indent) { 
  function esc(s){return s.replace(/[-\/&<> ]/g,function(c){         // Escape special chars
    return c==' '?'&nbsp;':'&#'+c.charCodeAt(0)+';';});}            
  var sm='<div class="xmt">',se='<div class="xel">',sd='<div class="xdt">',
      sa='<div class="xat">',tb='<div class="xtb">',tc='<div class="xtc">',
      ind=indent||'  ',sz='</div>',tz='</div>',re='',is='',ib,ob,at,i;
  if (!colorize) sm=se=sd=sa=sz='';   
  xml.match(/(?<=<).*(?=>)|$/s)[0].split(/>\s*</).forEach(function(nd){
    ob=('<'+nd+'>').match(/^(<[!?\/]?)(.*?)([?\/]?>)$/s);             // Split outer brackets
    ib=ob[2].match(/^(.*?)>(.*)<\/(.*)$/s)||['',ob[2],''];            // Split inner brackets 
    at=ib[1].match(/^--.*--$|=|('|").*?\1|[^\t\n\f \/>"'=]+/g)||['']; // Split attributes
    if (ob[1]=='</') is=is.substring(ind.length);                     // Decrease indent
    re+=tb+tc+esc(is)+tz+tc+sm+esc(ob[1])+sz+se+esc(at[0])+sz;
    for (i=1;i<at.length;i++) re+=(at[i]=="="?sm+"="+sz+sd+esc(at[++i]):sa+' '+at[i])+sz;
    re+=ib[2]?sm+esc('>')+sz+sd+esc(ib[2])+sz+sm+esc('</')+sz+se+ib[3]+sz:'';
    re+=sm+esc(ob[3])+sz+tz+tz;
    if (ob[1]+ob[3]+ib[2]=='<>') is+=ind;                             // Increase indent
  });
  return re;
}

for demo see https://jsfiddle.net/dkb0La16/

Cleodal answered 12/4, 2021 at 10:4 Comment(6)
Nice. Why are you using id= instead of class=? This code produces multiple elements with the same id.Belter
Thanks for the feedback. Totally messed up the code/link during initial post. Fixed.Cleodal
I also added the "s" flag. Some of my XML files include linefeeds. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Belter
Lightly confused .. where did you add the flag in the coding?Cleodal
I added an "s" to the end of all three match() regular repressions. (Not the split() or the replace().) It might have taken less, I didn't try all the combinations. This is easy enough to test. Add a newline after every ">" in your file.Belter
Understood and found a another bug with leading/trailing spaces. Should work now.Cleodal
R
3

I agree with Arjan on utilizing the <pre> tags. I was trying to decipher 'ugly' xml code in my html output before I tried this out about 2 days ago. Makes life much easier and keeps you sane.

Repairman answered 27/7, 2009 at 22:42 Comment(2)
Well, I'm not sure we couldn't have lived without the answer even if it were a comment, but well... Deleting it now may also purge the upvote, so wait until you've got at least 60 reputation then. :-)Costive
Now that a few years have passed, I guess deletion of this is due ;-) (Given its age, you'll keep the reputation, if I understand correctly.)Costive
F
1

This is not the best way to do this but you can get the xml as text and use RegExp to find and replace '>' with tabs according to the depth of the node and breaklines but I don't really know RegExp very well, sorry.

You can also use XSLT and transform it using javascript.
Check this link and take a look at this tutorial.

Fusil answered 27/7, 2009 at 10:55 Comment(0)
T
1

Use prettydiff.com/markup_beauty.js. This is capable of supporting invalid markup, fragments, and JSTL code.

<c:out value="<strong>text</strong>"/>

You can demo that application using a web tool at prettydiff.com. Just choose the "beautify" and "markup" options.

It is important that you use a proper tool to beautify your XML and not arbitrarily rush the job. Otherwise you will add white space tokens where they were not intended and remove them where they were intended. To raw data this may be consequential, but to human consumable content this destroys the integrity of your code, especially with regard to recursion.

Tenderhearted answered 15/12, 2010 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.