December 1, 2011

Vim XML Indent on Windows

Today I had some XML to check and I wanted to pretty format it inside gVim on my Windows 7 workstation. On Unix we’ve got xmllint who’s able to pretty format XML content, but I did not have it on Windows.

I knew I could do something like :%!xmllint in Vim and bam it would work. All I was needing was that external program. Instead of searching on the web for a port from Cygwin or something else, I did write a little tiny xmllint in Java. After that I just had to create some .bat file in my %PATH% and it worked like a charm.

import java.io.*;
import java.util.logging.*;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import com.sun.org.apache.xml.internal.serialize.*;

public class Xmllint {
    private static final Logger LOG = Logger.getAnonymousLogger();

    public static void main(String args[]) throws Exception {
        try {
            System.out.print(formatStdIn());
        } catch (Throwable e) {
            LOG.log(Level.SEVERE, "Could not indent XML.", e);
        }
    }

    static String formatStdIn() throws Throwable {
        final Document doc = parseStdIn();
        final OutputFormat format = new OutputFormat(doc, "UTF-8", true) { { setIndent(3); } };
        final Writer out = new StringWriter();
        new XMLSerializer(out, format).serialize(doc);
        return out.toString();
    }

    static Document parseStdIn() throws Throwable {
        final InputSource is = new InputSource(System.in);
        return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
    }
}

This is no übber-fancy Java, nothing hard to do, nor to understand. For sure, it is possible to enhance it so that it performs better.

I’m sure you know how to write a .bat file that will launch the Java program

@ECHO off
java Xmllint

I did map the call to xmllint in my vimrc to the F2 key with map <F2> <ESC>:%!xmllint<CR>:setf xml<CR>.

Before:

After:

I did a simple performance test, it’s way behind xmllint, but it should suit my needs at least on Windows, especially for an implementation that took 5 minutes:

$ wc sample.xml
    7712   26111  593764 sample.xml
$ time cat sample.xml | java Xmllint
    real  0m1.109s
    user  0m1.317s
    sys   0m0.093s
$ time xmllint --format sample.xml
   real  0m0.102s
   user  0m0.030s
   sys   0m0.016s

Enjoy your pretty XML in Vim on Windows :)

Alexandre Grison - //grison.me - @algrison