Vim Tips Wiki
(Remove html character entities)
(`%` (1 char) is easier to type and more comprehensible than `1,$` (3 chars).)
(6 intermediate revisions by 6 users not shown)
Line 3: Line 3:
 
|previous=348
 
|previous=348
 
|next=350
 
|next=350
|created=October 23, 2002
+
|created=2002
 
|complexity=basic
 
|complexity=basic
 
|author=Daniel Allen
 
|author=Daniel Allen
Line 13: Line 13:
 
If you open an xml document that is either totally or partially unindented, you can use the GNU libxml2 libary's xmllint to reformat and align your document. This is especially good if you want to save your xml documents using as little space as possible (which would be totally unindented). Just add this under the autocmd section of your [[vimrc]]:
 
If you open an xml document that is either totally or partially unindented, you can use the GNU libxml2 libary's xmllint to reformat and align your document. This is especially good if you want to save your xml documents using as little space as possible (which would be totally unindented). Just add this under the autocmd section of your [[vimrc]]:
 
<pre>
 
<pre>
au FileType xml exe ":silent 1,$!xmllint --format --recover - 2>/dev/null"
+
au FileType xml exe ":silent %!xmllint --format --recover - 2>/dev/null"
 
</pre>
 
</pre>
   
Line 19: Line 19:
   
 
==Comments==
 
==Comments==
  +
How can make it as a filter?
 
  +
===xmllint as a filter===
 
'''Q:''' How can make it as a filter?
   
 
I tried sth like
 
I tried sth like
Line 26: Line 28:
 
but it didn't work since xmllint doesn't take STDIN?
 
but it didn't work since xmllint doesn't take STDIN?
   
 
'''A:''' Notice the '-' given as the file argument to xmllint. This usually means stdin. So, the full command should be:
----
 
Notice the '-' given as the file argument to xmllint. This usually means stdin.
 
   
 
let &l:equalprg='xmllint --format --recover -'
----
 
Yes, xmllint can read from stdin, please note the '-' that occurs at the end of the options. This tells it to dump the file contents to the stdin pipe for xmllint. As far as I know, xmllint can be run in windows if you have gcc, but I am just projecting...look into it. If not, I am sure you can find something to take its place...the tip is just that, a tip, build on it.
 
   
 
'''A:''' Yes, xmllint can read from stdin, please note the '-' that occurs at the end of the options. This tells it to dump the file contents to the stdin pipe for xmllint. As far as I know, xmllint can be run in windows if you have gcc, but I am just projecting...look into it. If not, I am sure you can find something to take its place...the tip is just that, a tip, build on it.
----
 
  +
Regarding the filter question:
+
'''A:''' Regarding the filter question:
   
 
Start playing with
 
Start playing with
Line 43: Line 44:
   
 
----
 
----
  +
  +
===Fixing indenting of comment lines===
  +
 
"xmllint --format" indents comment lines to 0 which screws up the formatting for vim. A simple fix for single line comments can be made in indent/xml.vim. Copy indent/xml.vim to ~/.vim/xml.vim (Unix systems) and change the line that says:
 
"xmllint --format" indents comment lines to 0 which screws up the formatting for vim. A simple fix for single line comments can be made in indent/xml.vim. Copy indent/xml.vim to ~/.vim/xml.vim (Unix systems) and change the line that says:
   
Line 52: Line 56:
 
let lnum = a:lnum
 
let lnum = a:lnum
 
while lnum > 0
 
while lnum > 0
let lnum = prevnonblank(lnum - 1)
+
let lnum = prevnonblank(lnum - 1)
let line = getline(lnum)
+
let line = getline(lnum)
if strpart(line, 0, 4) != "<!--"
+
if line =~ '-->'
  +
let [lnum,watever] = searchpos('<!--','b')
break
 
endif
+
else
 
break
  +
endif
 
endwhile
 
endwhile
 
</pre>
 
</pre>
   
  +
Alone-on-line end-of-comment closing-tags may get badly indented though.
 
----
 
----
This might be helpful to you in making xmllint work with gvim under Windows,
 
   
  +
===xmllint on Windows===
http://www.pinkjuice.com/vim/vimrc.txt
 
   
  +
[http://code.google.com/p/xmllint/downloads/list Download xmllint for Windows]
----
 
  +
Use the following command, assuming xml file is open in Vim and xmllint.exe is in the same directory as the file:
Windows:
 
GNU libxml2 libary's xmllint.exe is buggy.
 
   
 
:% !xmllint.exe % --format
(See http://gnuwin32.sourceforge.net/packages.html)
 
   
  +
The first <code>%</code> ensures the content of the open file is replaced with the results of passing through xmllint. The order of the second <code>%</code> and the flag <code>--format</code> is important as otherwise xmllint will try to open a file with the name "--format".
Nothing happens. The input is the same as the output.
 
   
  +
====Altenative xmllint Windows binaries and instructions====
It does not work on Windows, because the xmllint.exe is unusable (at least in this respect).
 
   
  +
'''''Binaries'''''
This is true for June 2003.
 
 
*http://www.zlatkovic.com/projects/libxml/
 
*http://www.zlatkovic.com/projects/libxml/binaries.html
   
 
At previous wiki edit, the most recent version was http://www.zlatkovic.com/projects/libxml/libxml2-2.5.8.win32.zip
The syntax in vim would be easy:
 
   
  +
'''''Instructions'''''
Go into the xml-file and type:
 
:! xmllint.exe --format %
 
   
  +
For instructions see the Windows section under:
----
 
> It does not work on Windows, because the xmllint.exe<br>
 
> is unusable (at least in this respect)."
 
 
Try
 
*http://www.zlatkovic.com/projects/libxml/
 
*http://www.zlatkovic.com/projects/libxml/binaries.html .
 
 
Currently the latest version is http://www.zlatkovic.com/projects/libxml/libxml2-2.5.8.win32.zip
 
   
 
*http://www.pinkjuice.com/howto/vimxml/setup.xml#xmllint
> The syntax in vim would be easy:<br>
 
><br>
 
> Go into the xml-file and type:<br>
 
> :! xmllint.exe --format %
 
   
  +
====Other related links====
This would do nothing by itself AFAICS.
 
   
Check
 
*http://www.pinkjuice.com/howto/vimxml/setup.xml#xmllint ,
 
 
*http://www.pinkjuice.com/howto/vimxml/tasks.xml#prettyprinting and
 
*http://www.pinkjuice.com/howto/vimxml/tasks.xml#prettyprinting and
 
*http://www.pinkjuice.com/howto/vimxml/tasks.xml#validation
 
*http://www.pinkjuice.com/howto/vimxml/tasks.xml#validation
   
 
----
 
----
  +
===Alternatives to xmllint===
One problem with "xmllint --format" is that it turns non-ASCII UTF-8 characters into numeric references. This isn't a problem if you're taking the input of xmllint and editing it with an XML editor that internally converts everything to UTF-8 (like XMetal), but if what you want to do is use Vim to edit the file as a native UTF-8 (with :set encoding=utf8), then you *don't* want a bunch of numeric references instead of Unicode.
 
   
  +
====Built-in Search and Replace====
The xmllint developer knows about this issue but feels that adding an option to keep/not keep UTF-8 would complicate the code too much. So... is there another XML reformatter more suitable for producing output that Vim can use?
 
   
  +
Seriously consider using Vim's built-in search and replace functionality. See this [[Pretty-formatting_XML]] and the third comment (<code>:%s/></>\r</g</code> , etc).
----
 
Try http://www.pinkjuice.com/howto/vimxml/tasks.xml#prettyprinting
 
   
  +
====(HTML) Tidy====
----
 
I will change the solution described at the above URL since there is a very simple solution to the problem:
 
*http://mail.gnome.org/archives/xml/2003-August/msg00017.html
 
*http://mail.gnome.org/archives/xml/2003-August/msg00018.html
 
   
 
I was dissatisfied with what xmllint was doing to my XML documents. Its --format option seems to arbitrarily expand or remove blank lines. An alternative is to use the tidy program - formerly HTML Tidy. available at http://tidy.sourceforge.net/ I altered my .vimrc as follows:
:%!xmllint --format --encode UTF-8 -
 
 
----
 
Any ideas on how to use xmllint, but change the tab/indent width? It seems to filter, on windows, with 2 spaces for a tab.
 
 
----
 
Some of my documents are cut in half when I use xmllint with -. There is most likely some limit for stdin. Is it possible to use it in another way?
 
I'm on MS Windows with Vim 6.3...
 
 
----
 
I was dissatisfied with what xmllint was doing to my XML documents. Its --format option seems to arbitrarily expand or remove blank lines.
 
 
An alternative is to use the tidy program - formerly HTML Tidy. available at http://tidy.sourceforge.net/ I altered my .vimrc as follows:
 
   
 
au FileType xml exe ":silent 1,$!tidy --input-xml true --indent yes 2>/dev/null"
 
au FileType xml exe ":silent 1,$!tidy --input-xml true --indent yes 2>/dev/null"
   
----
 
 
Here's how you use tidy with xml on Windows:
 
Here's how you use tidy with xml on Windows:
   
 
au FileType xml exe ":silent 1,$!tidy -q -i -xml"
 
au FileType xml exe ":silent 1,$!tidy -q -i -xml"
   
----
 
 
I have this in my .vimrc
 
I have this in my .vimrc
 
" select xml text to format and hit ,x
 
" select xml text to format and hit ,x
Line 144: Line 119:
   
 
----
 
----
  +
===UTF-8 format===
In Unix/Linux, if you don't like the default indentation (2 spaces), set the $XMLLINT_INDENT environment variable, or prefix the xmllint command in your .vimrc file:
 
  +
au FileType xml exe ":silent 1,$!XMLLINT_INDENT=' ' xmllint --format --recover - 2>/dev/null"
 
 
'''Q:''' One problem with "xmllint --format" is that it turns non-ASCII UTF-8 characters into numeric references. This isn't a problem if you're taking the input of xmllint and editing it with an XML editor that internally converts everything to UTF-8 (like XMetal), but if what you want to do is use Vim to edit the file as a native UTF-8 (with :set encoding=utf8), then you *don't* want a bunch of numeric references instead of Unicode.
  +
 
The xmllint developer knows about this issue but feels that adding an option to keep/not keep UTF-8 would complicate the code too much. So... is there another XML reformatter more suitable for producing output that Vim can use?
   
  +
----
 
 
'''A:''' Try http://www.pinkjuice.com/howto/vimxml/tasks.xml#prettyprinting
Wy not using internal vim stuff:
 
  +
ggVG=
 
 
'''A:''' I will change the solution described at the above URL since there is a very simple solution to the problem:
 
*http://mail.gnome.org/archives/xml/2003-August/msg00017.html
 
*http://mail.gnome.org/archives/xml/2003-August/msg00018.html
  +
 
:%!xmllint --format --encode UTF-8 -
   
 
----
 
----
  +
===Changing tab/ident width===
 
'''Q:'''. Any ideas on how to use xmllint, but change the tab/indent width? It seems to filter, on windows, with 2 spaces for a tab.
  +
 
'''A:'''. In Unix/Linux, if you don't like the default indentation (2 spaces), set the $XMLLINT_INDENT environment variable, or prefix the xmllint command in your .vimrc file:
 
au FileType xml exe ":silent 1,$!XMLLINT_INDENT=' ' xmllint --format --recover - 2>/dev/null"

Revision as of 12:28, 29 March 2014

Tip 349 Printable Monobook Previous Next

created 2002 · complexity basic · author Daniel Allen · version 6.0


If you open an xml document that is either totally or partially unindented, you can use the GNU libxml2 libary's xmllint to reformat and align your document. This is especially good if you want to save your xml documents using as little space as possible (which would be totally unindented). Just add this under the autocmd section of your vimrc:

au FileType xml exe ":silent %!xmllint --format --recover - 2>/dev/null"

This instructs vim to take the entire contents of a *.xml file and pass it through xmllint, using the --format and --recover flags and silencing any errors that may occur. This is generally a very effective process and will only mess up on very poorly typed (a large amount of incorrect syntax) xml documents. Please note that xmllint only adds and removes structural space. It does not remove space from regular text nodes (as doing so would be incorrect).

Comments

xmllint as a filter

Q: How can make it as a filter?

I tried sth like

let&l:equalprg='xmllint --format --recover'

but it didn't work since xmllint doesn't take STDIN?

A: Notice the '-' given as the file argument to xmllint. This usually means stdin. So, the full command should be:

let &l:equalprg='xmllint --format --recover -'

A: Yes, xmllint can read from stdin, please note the '-' that occurs at the end of the options. This tells it to dump the file contents to the stdin pipe for xmllint. As far as I know, xmllint can be run in windows if you have gcc, but I am just projecting...look into it. If not, I am sure you can find something to take its place...the tip is just that, a tip, build on it.

A: Regarding the filter question:

Start playing with

" one or more lines:
vmap ,px !xmllint --format -<CR>
" pretty-print current line
nmap ,px !!xmllint --format -<CR>

Fixing indenting of comment lines

"xmllint --format" indents comment lines to 0 which screws up the formatting for vim. A simple fix for single line comments can be made in indent/xml.vim. Copy indent/xml.vim to ~/.vim/xml.vim (Unix systems) and change the line that says:

let lnum = prevnonblank(a:lnum - 1)

To this:

let lnum = a:lnum
while lnum > 0
    let lnum = prevnonblank(lnum - 1)
    let line = getline(lnum)
    if line =~ '-->'
        let [lnum,watever] = searchpos('<!--','b')
    else
        break
    endif
endwhile

Alone-on-line end-of-comment closing-tags may get badly indented though.


xmllint on Windows

Download xmllint for Windows Use the following command, assuming xml file is open in Vim and xmllint.exe is in the same directory as the file:

   :% !xmllint.exe % --format

The first % ensures the content of the open file is replaced with the results of passing through xmllint. The order of the second % and the flag --format is important as otherwise xmllint will try to open a file with the name "--format".

Altenative xmllint Windows binaries and instructions

Binaries

At previous wiki edit, the most recent version was http://www.zlatkovic.com/projects/libxml/libxml2-2.5.8.win32.zip

Instructions

For instructions see the Windows section under:

Other related links


Alternatives to xmllint

Built-in Search and Replace

Seriously consider using Vim's built-in search and replace functionality. See this Pretty-formatting_XML and the third comment (:%s/></>\r</g , etc).

(HTML) Tidy

I was dissatisfied with what xmllint was doing to my XML documents. Its --format option seems to arbitrarily expand or remove blank lines. An alternative is to use the tidy program - formerly HTML Tidy. available at http://tidy.sourceforge.net/ I altered my .vimrc as follows:

au FileType xml exe ":silent 1,$!tidy --input-xml true --indent yes 2>/dev/null"

Here's how you use tidy with xml on Windows:

au FileType xml exe ":silent 1,$!tidy -q -i -xml"

I have this in my .vimrc

" select xml text to format and hit ,x
vmap ,x :!tidy -q -i -xml<CR>

UTF-8 format

Q: One problem with "xmllint --format" is that it turns non-ASCII UTF-8 characters into numeric references. This isn't a problem if you're taking the input of xmllint and editing it with an XML editor that internally converts everything to UTF-8 (like XMetal), but if what you want to do is use Vim to edit the file as a native UTF-8 (with :set encoding=utf8), then you *don't* want a bunch of numeric references instead of Unicode.

The xmllint developer knows about this issue but feels that adding an option to keep/not keep UTF-8 would complicate the code too much. So... is there another XML reformatter more suitable for producing output that Vim can use?


A: Try http://www.pinkjuice.com/howto/vimxml/tasks.xml#prettyprinting

A: I will change the solution described at the above URL since there is a very simple solution to the problem:

:%!xmllint --format --encode UTF-8 -

Changing tab/ident width

Q:. Any ideas on how to use xmllint, but change the tab/indent width? It seems to filter, on windows, with 2 spaces for a tab.

A:. In Unix/Linux, if you don't like the default indentation (2 spaces), set the $XMLLINT_INDENT environment variable, or prefix the xmllint command in your .vimrc file:

au FileType xml exe ":silent 1,$!XMLLINT_INDENT='    ' xmllint --format --recover - 2>/dev/null"