Vim Tips Wiki

Changes: Pretty-formatting XML


Back to page

(Replaced content with "<?xml version="1.0" encoding="utf-8" ?><user_get_response><user><buyer_credit><good_num>0</good_num><level>0</level><score>0</score><total_num>0</total_num></buyer_credit>...")
Line 1: Line 1:
<?xml version="1.0" encoding="utf-8" ?><user_get_response><user><buyer_credit><good_num>0</good_num><level>0</level><score>0</score><total_num>0</total_num></buyer_credit><created>2012-05-11 17:23:03</created><last_visit>2012-05-11 17:23:03</last_visit><location></location><nick>liujinxiao2012</nick><seller_credit><good_num>0</good_num><level>0</level><score>0</score><total_num>0</total_num></seller_credit><sex>m</sex><type>C</type></user></user_get_response><!--top163184.cm3-->
Add this to your vimrc so you can type <code>:PrettyXML</code> and automatically pretty-format XML. Requires the command 'xmllint' in your PATH.
Note that this ignores significant whitespace! The result will be more readable, but it may not be semantically identical. I use this to read badly-formatted XML documents, not to save them.
function! DoPrettyXML()
" save the filetype so we can restore it later
let l:origft = &ft
set ft=
" delete the xml header if it exists. This will
" permit us to surround the document with fake tags
" without creating invalid xml.
1s/<?xml .*?>//e
" insert fake tags around the entire document.
" This will permit us to pretty-format excerpts of
" XML that may contain multiple top-level elements.
0put ='<PrettyXML>'
$put ='</PrettyXML>'
silent %!xmllint --format -
" xmllint will insert an <?xml?> header. it's easy enough to delete
" if you don't want it.
" delete the fake tags
" restore the 'normal' indentation, which is one extra level
" too deep due to the extra tags we wrapped around the document.
silent %<
" back to home
" restore the filetype
exe "set ft=" . l:origft
command! PrettyXML call DoPrettyXML()
I tried it on [ emblemsample.xml]. Buffer was empty after that.
:You need xmllint in your PATH (the buffer is replaced with the output from trying to run xmllint).
The following is my solution. gvim 7.0 on Windows XP. Ruby must be installed.
# download xmlformat
# copy xmlformat.rb to a folder, d:\bin for exmaple
# open the xml document to be formated in Vim
# type command
:% !ruby d:\bin\xmlformat.rb
From [[VimTip551|Automatically indent an XML file using XSLT]] comes this solution, which I prefer:
Hi, when I run this script I always get:
Error detected while processing function DoPrettyXML:
line 7:
:That is because line 7 (<code>1s/<?xml .*?>//</code>) tried to do a substitute in line 1, and gave an error because there was no matching text in your file. I added the 'e' flag so errors will be ignored. I also did some other style tweaks. Please reply with whether it works. --[[User:JohnBeckett|JohnBeckett]] 01:19, 8 October 2008 (UTC)
Here is a slightly less than elegant solution to cleanup XML that is all on one line. This does not require XSLT or any special plugins, just some regular expressions.
I put this in my _vimrc
map <F5> :%s/<\([^>]\)*>/\r&\r/g<enter>:g/^$/d<enter>vat=
map <F6> vatJxvito<right><left>x
map <F7> /\v^\s*([a-zA-Z\-0-9\$])<enter>qm<F6>nq@q1000@@:1<enter>
When I open an XML, I hit F5... this breaks it all into individual lines. Hit F7, if you want the XML node and content to be on the same line.
When using Unicode document, xmllint converts all characters to xml entities such as &#000;
the solution is to add encoding to the xmllint line, like this:
silent %!xmllint --encode UTF-8 --format -
but there may be some more generic way (to detect the encoding and set accordingly)
Based on the solution suggested in this tip, I created the following one, that provides some improvements:
# Open an XML file and type <leader>x in normal mode; the entire file will get formatted.
# Enter visual mode, select some (valid by itself!) XML code and also press <leader>x, only the selected text will be processed.
Just put the following in your vimrc:
" XML formatter
function! DoFormatXML() range
" Save the file type
let l:origft = &ft
" Clean the file type
set ft=
" Add fake initial tag (so we can process multiple top-level elements)
exe ":let l:beforeFirstLine=" . a:firstline . "-1"
if l:beforeFirstLine < 0
let l:beforeFirstLine=0
exe a:lastline . "put ='</PrettyXML>'"
exe l:beforeFirstLine . "put ='<PrettyXML>'"
exe ":let l:newLastLine=" . a:lastline . "+2"
if l:newLastLine > line('$')
let l:newLastLine=line('$')
" Remove XML header
exe ":" . a:firstline . "," . a:lastline . "s/<\?xml\\_.*\?>\\_s*//e"
" Recalculate last line of the edited code
let l:newLastLine=search('</PrettyXML>')
" Execute external formatter
exe ":silent " . a:firstline . "," . l:newLastLine . "!xmllint --noblanks --format --recover -"
" Recalculate first and last lines of the edited code
let l:newFirstLine=search('<PrettyXML>')
let l:newLastLine=search('</PrettyXML>')
" Get inner range
let l:innerFirstLine=l:newFirstLine+1
let l:innerLastLine=l:newLastLine-1
" Remove extra unnecessary indentation
exe ":silent " . l:innerFirstLine . "," . l:innerLastLine "s/^ //e"
" Remove fake tag
exe l:newLastLine . "d"
exe l:newFirstLine . "d"
" Put the cursor at the first line of the edited code
exe ":" . l:newFirstLine
" Restore the file type
exe "set ft=" . l:origft
command! -range=% FormatXML <line1>,<line2>call DoFormatXML()
nmap <silent> <leader>x :%FormatXML<CR>
vmap <silent> <leader>x :FormatXML<CR>
Thanks a lot to the original writer of this tip! :)
I hope you fine this useful! Cheers, [[User:Gsimone|Gsimone]] ([[User talk:Gsimone|talk]]) 22:17, December 19, 2012 (UTC).

Revision as of 07:29, March 8, 2013

<?xml version="1.0" encoding="utf-8" ?><user_get_response><user><buyer_credit><good_num>0</good_num><level>0</level><score>0</score><total_num>0</total_num></buyer_credit><created>2012-05-11 17:23:03</created><last_visit>2012-05-11 17:23:03</last_visit><location></location><nick>liujinxiao2012</nick><seller_credit><good_num>0</good_num><level>0</level><score>0</score><total_num>0</total_num></seller_credit><sex>m</sex><type>C</type></user></user_get_response>

Around Wikia's network

Random Wiki