Saturday, October 30, 2010

Formatting XML quickly

There are many times when I have come across badly formatted XML and need to prettify it instantly in order to aid readability or simply to paste into another document, like a blog post. There are plugins available (for example, Textpad's XMLTidy) which tidy up xml, but they involve pasting XML into a file and running a macro to clean it up, which can be slow, especially if you don't have an editor open.

So, I decided to write my own Java utility to format XML instantly. All you have to do is select some XML text, hit CTRL+C to save it to your clipboard, hit CTRL+ALT+F to invoke my formatting utility and finally hit CTRL+V to paste the nicely formatted XML somewhere else. This has made working with XML so much easier!

This is how you can set it up too:

The Java Source Code
Save the following source code to a file called XMLTidy.java and compile it using javac.

import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

/**
 * A useful utility for formatting xml.
 * Retrieves xml text from the system clipboard, formats it
 * and resaves it to the clipboard.
 */
public class XMLTidy {


  /**
   * Formats the specified xml string
   *
   * @param src the xml text to format
   * @return formatted xml
   * @throws ParserConfigurationException
   * @throws SAXException
   * @throws IOException
   */
  private static String tidyXml(String src)
      throws ParserConfigurationException, SAXException, IOException {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    InputSource is = new InputSource(new StringReader(src));
    Document document = db.parse(is);
    OutputFormat format = new OutputFormat(document);
    format.setLineWidth(65);
    format.setIndenting(true);
    format.setIndent(2);
    Writer out = new StringWriter();
    XMLSerializer serializer = new XMLSerializer(out, format);
    serializer.serialize(document);
    return out.toString();
  }

  /**
   * @return the text in the clipboard
   */
  private static String getClipboard() {
    Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard()
        .getContents(null);
    try {
      if (t != null &&
          t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        String text = (String) t.getTransferData(DataFlavor.stringFlavor);
        return text;
      }
    } catch (UnsupportedFlavorException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return "";
  }

  /**
   * @param str the text to set in the clipboard
   */
  private static void setClipboard(String str) {
    StringSelection ss = new StringSelection(str);
    Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
  }


  /**
   * Formats the xml supplied as an argument.
   * If no arguments are specified, formats the xml
   * in the clipboard.
   * @param args
   * @throws Exception
   */
  public static void main(String[] args) throws Exception {
    String in = args.length > 0 ? args[0] : getClipboard();
    if (in != null) {
      in = in.trim();
      if (in.charAt(0) == '<') {
        setClipboard(tidyXml(in));
      }
    }
  }
}
The Launcher Script
Create a bat file to launch the java program:
@echo off
%JAVA_HOME%\bin\java -cp \path\to\XMLTidy\classes XMLTidy %1
The Keyboard Shortcut
Finally create a keyboard shortcut to the launcher script as follows:
  • First, create a shortcut to the launcher script, by right-clicking the bat file and selecting "Create a shortcut".
  • Right-click the shortcut file and select "Properties".
  • Enter a "Shortcut key" on the Shortcut tab. For example, the shortcut key I use is CTRL+ALT+F
Try it out!
  • Select some badly formatted XML and copy it (using CTRL+C, for example).
  • Invoke XMLTidy by using the keyboard shortcut, CTRL+ALT+F.
  • Paste the XML (using CTRL+V, for example). The XML will be nicely formatted!

No comments:

Post a Comment