With some special configuration, Vim can become a powerful XML editor.
So you want to edit XML, but Vim is your favorite editor? The good news is that you don’t need an XML-specific editor! If you’re mortal, you’ll soon discover that editing raw XML can become tedious even in Vim (with its default configuration). But Vim is highly customizable and extensible. After a little tailoring, Vim performs excellently as an XML editor, with syntax highlighting, automatic indentation, navigational aids, and automation.
I will assume you have Vim set up the way you like it already on a Unix system, so we won’t fiddle much with your .vimrc file. Example 2-1 shows the bare minimum of what you need to make the rest of the hack work properly.
Example 2-1. Minimum .vimrc file
" $HOME/.vimrc " Don't pretend to be vi set nocompatible " Turn on syntax highlighting syntax on " Indicate that we want to detect filetypes and want to run filetype " plugins. filetype plugin on
Everything else will go in a filetype plug-in
. Vim will source this file
when it detects that you are editing an XML file (i.e., when the file
ends with the .xml suffix or if it has a proper
XML declaration). Example 2-2 is a good starter
ftplugin
. Save it to your home directory as
.vim/after/ftplugin/xml.vim. (The file
xml.vim is in the book’s file
archive.) The after
segment of the path means that
it will be sourced after all the normal scripts, plug-ins, and so on
are sourced, which allows you to override defaults and other plug-ins
without changing the original scripts. That makes upgrading those
scripts easier.
Example 2-2. The ftplugin xml.vim
" $VIMRUNTIME/after/ftplugin/xml.vim " Turn on auto-indentation set autoindent " Let's use a 2-character indent set shiftwidth=2 " With smarttab set, we can press tab at the beginning " of a line and get shiftwidth indent even though " tabstop is something else (e.g. the default 8) set smarttab " A lot of XML looks really bad and gets really confusing if " screen-wrapped. I prefer to turn off wrapping. set nowrap
On Windows, your vimrc file is
$VIM\_vimrc (default
C:vim\_vimrc). Consider
$VIMRUNTIME by default to be
C:vimvimfiles. So, for example, you should
install the ftplugin in
C:vimvimfilesafterftplugin. See
:help dos-locations
for more details.
All XML files can benefit from the generic XML syntax highlighting included with Vim. But not all XML is created equal. Imagine you came up with a nifty XML format for your data and now you want certain items to be emphasized to make editing and reading easier. That probably wasn’t too hard to imagine, was it?
There are two steps to customized syntax highlighting. The first step is telling Vim how to differentiate your special XML from regular XML. The second step is to define how your special syntax highlighting differs.
We’ll work with a simple RSS 2.0 file
[Hack #83]
as our example, called
frodo.rss (Example 2-3). Figure 2-5 shows frodo.rss
in
gVim, a GUI version of Vim (ftp://ftp.vim.org/pub/vim/pc/gvim63.zip), on
Debian (GTK2 in Grand Canyon theme).
Example 2-3. frodo.rss
<?xml version="1.0"?> <rss version="2.0"> <channel> <title>The Gondor Times</title> <link>http://www.gondortimes.com/</link> <description>News for the race of men.</description> <item> <title>Sauron defeated!</title> <category>Middle Earth</category> <description>Now comes the story of Nine-fingered Frodo and the Ring of Doom.</description> <guid>http://www.gondortimes.com/middleearth/3/25</guid> </item> </channel> </rss>
In order for Vim to treat an XML vocabulary specially, it needs to
differentiate it from normal XML. The easiest way to do this is by
using a different file extension. Setting up a new
filetype
with a unique extension is
straightforward (see :help new-filetype
).
Let’s define a filetype
for RSS
2.0 files with .vim/filetype.vim, as shown in
Example 2-4.
Example 2-4. filetype.vim
" my filetype file if exists("did_load_filetypes") finish endif augroup filetypedetect au! BufRead,BufNewFile *.rss set filetype=rss augroup END
Now when you restart Vim and edit frodo.rss, you
should notice that it is not being recognized as XML any longer. That
means no syntax highlighting, no ftplugin
, nada.
Wait, don’t despair! You don’t need
to rewrite syntax highlighting for XML.
Let’s set a modest goal for ourselves: highlight the
channel
and item
tag names in
bold, and make category tag names a different color. The way to
achieve this is to utilize the
xmlTagHook
cluster provided by the
syntax/xml.vim author. A
syntax
cluster is an open-ended bag of syntax groups that can occur in
certain places. That means we can define a syntax group and say that
it belongs to the xmlTagHook
cluster, and it will
be matched only when the match would otherwise be a regular XML tag.
Let’s look at Example 2-5.
Example 2-5. rss.vim
" Vim syntax file " Language: RSS 2.0 " Maintainer: Hans Fugal <[email protected]> " Last Change: Thu, 11 Mar 2004 15:44:28 -0700 " REFERENCES: " 1. http://blogs.law.harvard.edu/tech/rss " Quit when a syntax file was already loaded if exists("b:current_syntax") finish endif " Base our syntax highlighting on xml runtime syntax/xml.vim syn match rssElement /<channel>/ syn match rssElement /<item>/ syn match rssCategory /<category>/ syn cluster xmlTagHook add=rssElement,rssCategory highlight rssElement cterm=bold gui=bold highlight link rssCategory Statement
Those syn match
lines define the patterns that
will match the rssElement
group. The
<
and >
match the
beginning and end of a word (tag), respectively. So we are matching
the full word channel
or the full word
item
. The syn cluster
line adds
our new rssElement
and
rssCategory
groups to the
xmlTagHook
cluster. The
highlight
lines define how we want things to look.
You’ll want to look up the help on
highlight
because that’s where
your creativity can really flow.
syntax/xml.vim also provides these hooks:
xmlAttribHook
xmlNamespaceHook
xmlTagHook
xmlStartTagHook
xmlRegionHook
xmlCdataHook
See the comments in syntax/xml.vim from the Vim distribution for more details.
OK, so now you have syntax highlighting, but you’ve
lost the behaviors we defined in
after/ftplugin/xml.vim, and many more behaviors
that we’ll talk about shortly that you certainly
won’t want to miss out on. The easiest solution to
this problem is to create a symbolic link from
after/ftplugin/xml.vim to
after/ftplugin/rss.vim (or whatever new
filetype
you created).
Vim’s
auto-indent is OK, but smart indentation is better. Enabling smart
indent for XML in Vim is as simple as putting filetype indent on
in your .vimrc or in your
ftplugin. If you don’t like the
XML smart indentation but do like filetype indent on
in your .vimrc, then you can put
let b:did_indent
= 1
in your
XML ftplugin.
Sometimes you want to clean up the formatting of the whole XML file.
To do this you can either type gg=G
with
filetype indent on
or use an external filter. The
internal method is prone to messing with your whitespace in verbatim
elements, while external formatters such as
Paul
DuBois’s xmlformat (http://www.kitebird.com/software/xmlformat/)
or xmllint with --format
(see
[Hack #9]
) can do a much better
job.
To use xmlformat to format your XML in Vim, try the following command (assuming xmlformat is installed and in the path):
:!xmlformat %
To use xmllint, try:
:!xmllint --format %
Both of these commands are good candidates for mappings (see “Automation”).
Folding
is a new feature in Vim Version 6 and later that allows you to
collapse arbitrary portions of your document down to one line,
similar to collapsing and expanding trees in menus or dialog boxes.
XML lends itself well to folding because of its hierarchical nature.
There are several ways to do folding (see :help folding
). The easiest way to fold XML is to use the syntax
method. To enable folding in XML documents, add the following lines
to your XML ftplugin:
set foldenable set foldmethod=syntax set foldlevel=1
The set foldlevel=1
line tells Vim to leave the
top element unfolded. You can tune this number to your liking. You
can also tune it to specific files by using a modeline at the bottom
of the file; for example:
<!-- vim:foldlevel=5 -->
All fold commands start with z
.
zo
opens a fold, zc
closes one,
zm
increases the number of folds (decreases
foldlevel
), and zr
reduces the
number of folds. zM
and zR
fold
everything and nothing, respectively. Figure 2-6
shows an example of folding with frodo.rss.
The biggest problem with editing XML by hand is all that typing. Vim can help you avoid a lot of that extra typing thanks to some wonderful contributed scripts that can be found at http://www.vim.org.
Extends the behavior of %
and includes support for
XML. Pressing %
will take you from opening tag to
closing tag, and vice versa. It was written by Benji Fisher. See
http://www.vim.org/scripts/script.php?script_id=39.
Closes the next open tag when you press Ctrl-_. This is a real boon
when you get tired of typing things like
</xsl:apply-templates>
. It was written by
Steven Mueller. See http://www.vim.org/scripts/script.php?script_id=13.
A handy script for commenting and uncommenting segments of your file, and supports XML very well. It was written by Meikel Brandmeyer. See http://www.vim.org/scripts/script.php?script_id=23.
The mother of all XML Vim scripts is
xmledit.vim. It further enhances
%
, provides other navigation facilities,
auto-creates closing tags, can %delete
a
surrounding tag, and has a dialog-driven tag creator in visual mode
that will wrap a tag around whatever is selected.
xmledit.vim makes writing XML much less tedious,
and it makes well-formedness easier than ever to achieve. It was
written by Devin Weaver. See http://www.vim.org/scripts/script.php?script_id=301.
There are many other scripts and tips available. In addition to
general scripts and tips, you may find yourself with specific desires
for automation. Do you create similar XML documents frequently by
hand? Use a template (see :help :r
). Maybe you
want to map xmlformat to a simple keystroke (see
:help key-mapping
). Perhaps you type
<xsl:apply-templates>
far too often and
would prefer to type <a-t>
and watch it
magically expand to <xsl:apply-templates>
(see :help abbrev
). Maybe an abbreviation
isn’t enough and you want
<a-t>
to expand to
<xsl:apply-templates select="">
with the
cursor right between the quotation marks, in which case
you’re in the realm of scripting (see :help vim-script-info
). If you don’t like
Vim’s scripting language, you can extend Vim with
Perl, Python, Ruby, or Tcl. With Vim, the sky’s the
limit.
The Vim help files: :help
or online at http://vimdoc.sourceforge.net/
Tobias Rief’s excellent HOWTO on Vim as an XML editor: http://www.pinkjuice.com/howto/vimxml/
Steve Oualline’s Vi Improved—Vim (New Riders Press) is a must-have reference for any serious Vimmer (also available to read online at http://vimdoc.sourceforge.net/)
Vim scripts: http://www.vim.org/scripts/script_search_results.php?keywords=xml&script_type=&orderby=rating&direction=descending&search=search
—Hans Fugal
3.140.198.43