You might already have to work with huge XML files. Using regexp searches aren't really handy as you easily get lost in the XML file. I am currently working with a really enormous XML file. I have then written some small Perl and Vim script to search in XML files using XPath. I have been mostly inspired by those pages:
- http://use.perl.org/~Ovid/journal/36682 for the Perl script base
- http://vim.wikia.com/wiki/Temporarily_replace_grep_with_a_custom_program for the Vim integration part
Installing
The Perl program mentioned in the first link has been heavily changed to
report a clean filename, line number and message to use in the Vim
quickfix window. All you need is to copy the Perl script into your PATH
and name it xpath
(really original name), then copy the .vimrc
fragment into your .vimrc
file.
Perl script:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::LibXML;
my ( $filename, $xpath, $rname ) = @ARGV;
unless ( defined $rname ) {
$rname = $filename;
}
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file( $filename );
my $xc = XML::LibXML::XPathContext->new( $doc );
my $nodes = $xc->findnodes( $xpath );
my $found = 0;
foreach my $node ( $nodes->get_nodelist ) {
$found++;
print $rname, ":", $node->line_number(), " ", $node->nodePath( ) ,"\n";
}
unless ( $found ) {
print "No XML found matching xpath '$xpath'\n";
}
.vimrc
fragment:
function! XMLMappings()
noremap ;xp :call Xpath()
endfunction
function! Xpath()
" Needs to get the real file name for the quickfix window
let realname = bufname( "%" )
" Write the buffer to a temp file
let filename = tempname()
let lines = getline( 1, "$" )
call writefile( lines, filename )
let xpath = input("Enter xpath expression: ")
let tmp1=&grepprg
let tmp2=&grepformat
set grepformat=%f:%l\ %m
set grepprg=xpath
exe "grep ".escape(filename, ' \')." \"".xpath."\" ".escape(realname, ' \')
let &grepprg=tmp1
let &grepformat=tmp2
endfunction
Using
To use this feature, open an XML file and type <leader>xp
, then type
your XPath expression. <leader>
is the '\
' key by default but you
may have changed it. The Perl script handles the namespaces in the
XPath expressions.