Formatting XML in Sublime Text 2 (xmllint)


I'm always looking for the best tools to make my life easier. In this constant search for the best text editor for coding and general text work (mainly XML) I decided to try the amazing Sublime Text 2.

I was using TextWrangler for a while and had finally manage to get XML pretty formatting to work on it again but I was struggling to get the same experience out of Sublime Text 2. My ideal workflow is to paste some unformatted XML, press some hotkey combination and end up something pretty. Because there's always someone with with the same problem, a quick google search took me to this page where there are a couple of scripts to do just this. Read that first to get a grip on how to implement these simple scripts.

While this seemed to work pretty well I was still having some trouble with some files that weren't being formatted exactly as I expected. These scripts use the open source tidy command, which is pretty cool. However, for some reason my XMLs (which included some CDATA elements) were not being formatted properly. So I decided to use xmllint instead, just like I had done before in TextWrangler.

Turns out it's pretty easy to change the script to use xmllint instead of tidy. I created a new file called tidy_xml_lint.py, saved it to the same place where user scripts are supposed to be (OS X: ~/Library/Application Support/Sublime Text 2/Packages/User/ and WINDOWS: %APPDATA%\Sublime Text 2\Packages\User), and changed the keymap file to reflect the new command name.

Here's the code for OS X (or get the gist here https://gist.github.com/bergonzzi/7977004):

import sublime, sublime_plugin, subprocess

class TidyXmlLintCommand(sublime_plugin.TextCommand):
  def run(self, edit):
    command = "XMLLINT_INDENT=$'\t' xmllint --format --encode utf-8 -"

    # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
    xmlRegion = sublime.Region(0, self.view.size())
    p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
    result, err = p.communicate(self.view.substr(self.view.sel()[0]).encode('utf-8'))

    if err != "":
      self.view.set_status('xmllint', "xmllint: "+err)
      sublime.set_timeout(self.clear,10000)
    else:
      self.view.replace(edit, self.view.sel()[0], result.decode('utf-8'))
      sublime.set_timeout(self.clear,0)

  def clear(self):
    self.view.erase_status('xmllint')

Don't forget to change your key bindings file as well (Preferences > Key Bindings - User)

[ { "keys": ["ctrl+shift+x"], "command": "tidy_xml_lint" }, { "keys": ["ctrl+shift+j"], "command": "prettify_json" } ]

Update:

This article became quite popular, it's great to see it's helping so many people! There are some good comments below so I'm going add the best ones here for your convenience.

Michael Argentini offers a nice tip to add this command to the Format menu:

You can add this command to the Selection>Format submenu as well! Create a file named “Main.sublime-menu” in the Packages>User folder where you created the Python file above. Then put the following in it:

[
    {
        "caption": "Selection",
        "children": [
            {
                "caption": "Format",
                "children": [
                    {
                        "caption": "Tidy with XML Lint",
                        "command": "tidy_xml_lint"
                    }
                ],
                "id": "format"
            }
        ],
        "id": "selection"
    }
]

Dimitris Baltas offers a solution for the dollar sign problem:

(...)
I also had the issue with the $ sign that Jon G mentioned. (on sublime-text-2, ubuntu 12.04)
I resolved it by removing the $ in line 5
from
command = "XMLLINT_INDENT=$'\t' xmllint --format --encode utf-8 -"
to
command = "XMLLINT_INDENT='\t' xmllint --format --encode utf-8 -"

Protke was kind enough to summarize the necessary changes for Windows users, here's the full script (or get the gist here https://gist.github.com/protke/7193842):

import sublime, sublime_plugin, subprocess

class TidyXmlLintCommand(sublime_plugin.TextCommand):
  def run(self, edit):
    command = "xmllint -format -encode utf-8 -"

    # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
    # discussion on http://www.bergspot.com/blog/2012/05/formatting-xml-in-sublime-text-2-xmllint/
    if self.view.sel()[0].empty():
      xmlRegion = sublime.Region(0, self.view.size())
    else:
      xmlRegion = self.view.sel()[0]

    p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
    result, err = p.communicate(self.view.substr(xmlRegion).encode('utf-8'))

    if err != b"":
      self.view.set_status('xmllint', "xmllint: " + err.decode("utf-8"))
      sublime.set_timeout(self.clear,10000)
    else:
      self.view.replace(edit, self.view.sel()[0], result.decode('utf-8').replace("\r",""))
      sublime.set_timeout(self.clear,0)

  def clear(self):
    self.view.erase_status('xmllint')

As an alternative to installing your own plugin there's also a package available that you can easily install from within Sublime Text 2. See here https://github.com/alek-sys/sublimetext_indentxml for more details.

79 comments to Formatting XML in Sublime Text 2 (xmllint)

  • One thing I’d like to say is always that before acquiring more personal computer memory, consider the machine within which it could well be installed. When the machine can be running Windows XP, for instance, the particular memory threshold is 3.25GB. Applying in excess of this would merely constitute any waste. Make sure one’s mother board can handle an upgrade quantity, as well. Good blog post.

  • Ida Jervois

    Hi!

    You Need Leads, Sales, Conversions, Traffic for bergspot.com ? Will Findet…

    I WILL SEND 5 MILLION MESSAGES VIA WEBSITE CONTACT FORM

    Don’t believe me? Since you’re reading this message then you’re living proof that contact form advertising works!
    We can send your ad to people via their Website Contact Form.

    IF YOU ARE INTERESTED, Contact us => lisaf2zw526@gmail.com

    Regards,
    Jervois

  • You have actually done your analysis. The graph pattern set up nicely as well as is currently giving you a signal to
    buy. You position your order as well as look at the display screen to verify it.
    Now what?

    Unless you’re a really temporary investor such as a day-trader, maybe the most effective thing you can do is begin viewing some motion pictures.
    At least you should escape the display display and do something else.
    Do not sit and enjoy each tic of your new position out there.

    Your mind will start playing tricks with you.

    I can’t stress how crucial it is to eliminate emotions from your trading.
    Emotions such as concern, greed and also hope can cause several trading errors
    which will actually injure your trading outcomes.
    I’m not stating you should not check your brand-new setting in the market.
    Just do not stare at the screen, then live as well as pass away on each tic motion. The absolute best investors
    remove most or every one of their emotions when trading.
    This is done by following a solid trading strategy and also comprehending the emotional
    component of trading.

    The most effective point you can do is put in a tactical quit loss to maintain your
    loss small in instance the market violates you. Area this quit loss listed
    below an important assistance location. It’s best to
    never risk more than 10% from the buy factor. This will assist to keep emotion out of your trading which will enhance your trading outcomes.
    So go enjoy a fantastic film and enhance your trading at the same time.

    Gary E Kerkow, creator of Tradingmarkets4u, is a stock and assets market specialist.
    He is an effective trader as well as instructor, with over two decades experience.

    How great would it be if you could go to the
    flicks totally free. Yes you read that right, go
    see every one of the brand-new launch block buster, and also never ever need to spend
    a solitary dime. Individuals see motion pictures in this manner every one of the moment.
    They recognize a key that extremely couple of people
    know. They recognize that companies will employ you to take a look
    at the customer support skills that their staff members have.

    Heads of effective organisations know that mystery consumers are the only
    method from them to really review people’s worth values.

    What you would certainly do as an enigma movie theater shopper that
    you will, most likely to the flicks, making certain to see the concession stand, after that you will go, sit down enjoy your motion picture and go home.
    Bear in mind that while you are in the cinema to take the time to
    look around, is the theater tidy, is there any type of busted
    seats? Prior to the movie begins go to the washroom, are they clean do every one of the stalls lock?
    After he motion picture head back to the washroom to see what
    type of order it is in now? In order to do your job correctly you have to take psychological notes.

    When you obtain home you will certainly require to evaluate your experience.
    Include in the record, exactly how the workers
    greeted you. Reference is the cinema was tidy, and also anything else that left a long lasting expression on you,
    whether excellent or bad. The far better your reports are,
    the even more work that you will certainly be offered.

    If you require loan now, like I suggest in the next
    hr, attempt what I did. I am making more money now than in my old service as well as
    you can as well, check out the remarkable, real story, in the link listed below.
    When I joined I was unconvinced for just 10 secs prior to I realized what this was.
    I was smiling from ear to ear and also you will certainly also.

    Think of increasing your cash weekly without or little threat!
    To discover a verified listing of Million Buck Firms using you their items at 75% compensation to
    you. Click the link listed below to learn HOW you will begin intensifying your capital towards your very first Million Dollars at the very easy corporate cash program.

  • Among the best gadgets on the marketplace to is from Microsoft, which has actually
    made the experience of viewing films on Zune an unforgettable experience.
    The Zune is a multimedia gamer that does greater than allow one to
    view video clips.

    Ultimate Gamer – It can likewise hold songs, present
    all kind of images in numerous layouts, and there is also software application and games designed specifically on the system.
    Nonetheless, it is viewing flicks on its huge and also lovely
    screen that influences customer choices the most when they are in the market for a brand-new mp3/ video gamer.
    Let’s have a look at the advantages of having a Zune as a video clip gamer.

    Screen Estate

    Big Screen – Among the highlights of the Zune gamer is its 240×320 pixel display that
    is so huge that you do not need to stress your eyes when you are viewing a video clip
    or a motion picture. This is among the biggest screens on a mobile mp3/
    video player on the market.

    The 3-inch screen is vibrantly lit and also if you were to download and
    install or transform a DVD onto this gadget,
    the top quality would certainly be no different than if you were
    watching on a television display. The crisp and also clear display is something that numerous Zune proprietors anticipate whenever
    they use this tool.

  • aussi. A chaque fois. Je me branle tous les combien moi  Tous les jours 

  • Wilbert Gannon

    One thing I would like to say is car insurance cancellation is a feared experience and if you’re doing the appropriate things being a driver you’ll not get one. Some individuals do obtain notice that they have been officially dumped by the insurance company and many have to struggle to get added insurance from a cancellation. Inexpensive auto insurance rates tend to be hard to get from a cancellation. Having the main reasons concerning the auto insurance cancellation can help people prevent completely losing in one of the most important privileges offered. Thanks for the tips shared via your blog.

  • Hi. I see that you don’t update your site too often. I know that
    writing posts is boring and time consuming. But did you know that there is
    a tool that allows you to create new articles using existing content (from article directories or other blogs from
    your niche)? And it does it very well. The new articles are
    high quality and pass the copyscape test. You should try miftolo’s tools

  • Thank you for sharing excellent informations. Your web-site is very cool. I am impressed by the details that you have on this web site. It reveals how nicely you understand this subject. Bookmarked this web page, will come back for extra articles. You, my friend, ROCK! I found simply the info I already searched everywhere and just couldn’t come across. What a perfect web site.

  • some cheap softwares does not offer good online technical support so i would caution about using them,

  • Fake A Lange & Sohne watches are wonderful collections of wrist watches, attractive, dignified, and elegant accessory for fashion.

  • I have never really reviewed muh for tests. When I Have needed to, it’s usually been because I
    neded tto memorize a lot of facts, for example obscure vocabulary, or because I needed to memorize some important formulas.

    The math classes began being somewhat challenging in ninth grade,
    so I needed to review forr ninth grade mathematiics tests, and I quit paying attention in class iin tenth grade so that I really could read,
    so I bsgan needing to learn some at home.

  • ask

    I was recommended this website by way of my cousin. I am now not certain whether this
    publish is written by him as nobody else understand such precise about
    my difficulty. You’re amazing! Thanks!

  • Jens Klein

    Inspired by your article and code I wrote a similar plugin using xml_pp to format the xml. Code here
    https://gist.github.com/jensens/4fc631616f5ef9ac4c6b

  • I have created a complete instructions gist for Sublime Text 2 here:

    https://gist.github.com/cbmeeks/8317048

  • Justin

    I modified Jacob’s Win7 Sublime 3 code so that the CR tag doesn’t appear after reformatting, here’s the altered line of code:

    self.view.replace(edit, self.view.sel()[0], result.decode(‘utf-8′).replace(“\r”, “”))

    • Protke!

      So, integrating everything said so far, here it is, for W7 users:
      import sublime, sublime_plugin, subprocess

      class TidyXmlLintCommand(sublime_plugin.TextCommand):
      def run(self, edit):
      command = "xmllint -format -encode utf-8 -"

      # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
      # discussion on http://www.bergspot.com/blog/2012/05/formatting-xml-in-sublime-text-2-xmllint/
      if self.view.sel()[0].empty():
      xmlRegion = sublime.Region(0, self.view.size())
      else:
      xmlRegion = self.view.sel()[0]

      p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
      result, err = p.communicate(self.view.substr(xmlRegion).encode('utf-8'))

      if err != b"":
      self.view.set_status('xmllint', "xmllint: " + err.decode("utf-8"))
      sublime.set_timeout(self.clear,10000)
      else:
      self.view.replace(edit, self.view.sel()[0], result.decode('utf-8').replace("\r",""))
      sublime.set_timeout(self.clear,0)

      def clear(self):
      self.view.erase_status('xmllint')

      or just

      https://gist.github.com/protke/7193842

  • Vladox

    Here an improved version that detects if no selection has been and applies the formatting to all the text as you would expect…

    https://gist.github.com/vladox/6601324


    import sublime, sublime_plugin, subprocess

    class TidyXmlLintCommand(sublime_plugin.TextCommand):
    def run(self, edit):
    command = "XMLLINT_INDENT='\t' xmllint --format --encode utf-8 -"

    # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
    if self.view.sel()[0].empty():
    xmlRegion = sublime.Region(0, self.view.size())
    else:
    xmlRegion = self.view.sel()[0]

    p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
    result, err = p.communicate(self.view.substr(xmlRegion).encode('utf-8'))

    if err != b"":
    self.view.set_status('xmllint', "xmllint: " + err.decode("utf-8"))
    sublime.set_timeout(self.clear,10000)
    else:
    self.view.replace(edit, xmlRegion, result.decode('utf-8'))
    sublime.set_timeout(self.clear,0)

    def clear(self):
    self.view.erase_status('xmllint')

  • […] When I attended the BuildWindows conference this summer, I saw many of the presenters using Sublime as a text editor. It runs on both PCs with Windows and Mac. It also works on Linux. It seemed to be the consensus editor of choice. http://www.sublimetext.com/. I have enabled my Sublime plugin to prettify the XML files I work with on a regular basis. I used this tip here: http://www.bergspot.com/blog/2012/05/formatting-xml-in-sublime-text-2-xmllint/ […]

  • On Windows, I needed to use the version of xmllint from Google that allows the console redirection support. The 2009 version I had would not work.

  • Devid

    I just can’t manage to do this under Windows 7. I installed xmllint via package manager, but when i select xmllint format nothing happens. I also installed the xmllint.exe file on my Desktop and tried to Format via command prompt and it works. I have put the xmllint in my variable path but from sublime text 2 it is not working as it should, i get errors. I have also tried to give it my absolute path but that is not working either

  • Looks like there’s a package for xmllint now which offers indentation, formatting, validation, etc.

    Open command palette: Cmd-Shift-P
    select “Package Control: Install Package”
    start typing “xmllint” and hit enter

    After it’s installed (progress in the footer bar), you can open command palatte and type xmllint to see the options. Pretty nice.

  • Dimitris Baltas

    Jacob’s trick with b”
    if err != b”:
    made the plugin working on sublime text 3 on my ubuntu 12.04 installation.
    https://gist.github.com/dbaltas/6054139

  • Jacob Dingus

    On Windows 7, Sublime Text 3, I had to modify the command line as Vivek mentioned above, as well as the error handling, checking for b” and it will only print(err) it has trouble converting strings it seems like.

    import sublime, sublime_plugin, subprocess

    class TidyXmlLintCommand(sublime_plugin.TextCommand):
    def run(self, edit):
    command = "xmllint --format --encode utf-8 -"

    # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
    xmlRegion = sublime.Region(0, self.view.size())
    p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
    result, err = p.communicate(self.view.substr(self.view.sel()[0]).encode('utf-8'))

    if err != b'':
    print(err)
    sublime.set_timeout(self.clear,10000)
    else:
    self.view.replace(edit, self.view.sel()[0], result.decode('utf-8'))
    sublime.set_timeout(self.clear,0)

    def clear(self):
    self.view.erase_status('xmllint')

  • kourouma

    Thank you for this amazing work. It work like I was expecting tool to do. You save my time.

  • Bala

    Thank you very much it works fine. In your reply sb:authors starting element duplicated, please remove it for others to refer with out any confusion.

  • Bala

    sorry this is the code

    <sb:authors><sb:author><INS><ce:given-name>J.</ce:given-name></INS><INS><ce:surname>Bachman</ce:surname></INS></sb:author></sb:authors>

    • Hi,

      You can format xml with namespaces as well, in your example you’d have to add the namespace declaration otherwise it’s not valid xml (because you’re using name prefixes, see more info here http://www.w3schools.com/xml/xml_namespaces.asp).

      Try formatting this and you’ll see it works fine:


      <sb:authors xmlns:sb="http://www.w3.org/TR/html4/" xmlns:ce="http://www.w3.org/TR/html4/"><sb:author><INS><ce:given-name>J.</ce:given-name></INS><INS><ce:surname>Bachman</ce:surname></INS></sb:author></sb:authors>

  • Bala

    Hi,

    Very userfuly and nice post. Thank you very much for your help. Is there any chance to format the xml having name space elements as mentioned below:

    G.Bala

    • di:&bnsp;tViolette : bien sur qu’ils sont beaux mes rideaux ! J’suis pauvre mais j’ai encore du goût bordel ! D’ailleurs je crois que c’est en les achetant que je me suis endettée.

  • Damir

    Hello ! What theme for Sublime Text do you use? Nice colors :)

  • […] formatting XML using xmllint- follow the instructions to get your own XML tidy this one preserves spaces as some XML Tidier will remove spaces after certain tags for example house winterfell will become housewinterfell after you tidy it which could lead to errors in copy. […]

  • Beezer

    Can anyone tell me how to use XMLlint to validate an XML file against a schema? I have the Sublime LInter plugin installed, but I’m unsure of how to specify a schema location. Thanks.

  • Vivek

    To make this work on Windows, change the line with the command to:

    command = “xmllint –format –encode utf-8 -”

    Also, make sure that xmllint.exe is in your default environment PATH. You should restart Sublime if you changed PATH externally.

  • Dimitris Baltas

    Thanks for the great plugin.
    I also had the issue with the $ sign that Jon G mentioned. (on sublime-text-2, ubuntu 12.04)
    I resolved it by removing the $ in line 5
    from
    command = “XMLLINT_INDENT=$’\t’ xmllint –format –encode utf-8 -”
    to
    command = “XMLLINT_INDENT=’\t’ xmllint –format –encode utf-8 -”

    A nice addition would be the ability to format the whole document if there is no selected area.

  • Thanks for this!! I’m slowly getting rid of all the little things I go back to TextMate for, and this was a biggie. So awesome!

  • You can add this command to the Selection>Format submenu as well! Create a file named “Main.sublime-menu” in the Packages>User folder where you created the Python file above. Then put the following in it:


    [
    {
    "id": "selection",
    "caption": "Selection",
    "children":
    [
    {
    "id": "format",
    "caption": "Format",
    "children":
    [
    {
    "caption": "Tidy with XML Lint",
    "command": "tidy_xml_lint"
    }
    ]
    }
    ]
    }
    ]

  • Jon G

    First off, thanks. This is great.
    However, I have one problem and I’m not sure how to solve it. When I use xmllint, instead of getting tabs I get a dollar sign and then the tab. Any idea how to pull the dollar sign out?

  • Excellent, Nice and easy, works like a charm. Now I only have to get it in the command window (shift-command-p) because I always forget key shortcuts after not working with them for a while :)
    Thanks

  • Eddie Ridwan

    Works for me. Much appreciated.

  • […] that it's missing. This is where the plugin system and the community proves useful. I found this post which is pretty straight forward but for my setup didn't work (Windows 7). I made it work very […]

  • Thanks, works great. I came from TextMate and looked for the exact same thing!

  • Eli Shalnev

    Hi, do you know how could i make it work on Windows?
    I downloaded and installed the HTML Tidy as suggested in the github article..but..
    I’m getting this error:

    ————–
    Traceback (most recent call last):
    File “.\sublime_plugin.py”, line 350, in run_
    File “.\tidy_xml_lint.py”, line 10, in run
    result, err = p.communicate(self.view.substr(self.view.sel()[0]).encode(‘utf-8′))
    File “.\subprocess.py”, line 701, in communicate
    File “.\subprocess.py”, line 911, in _communicate
    IOError: [Errno 32] Broken pipe
    ————–

    Thanks in advance!

  • Bob Greene

    Thanks for the post. I’m just getting started with Sublime and still trying to match my old toolbox. This will help lots.

Leave a Reply to Damir Cancel reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>