Format XML in Notepad++, VS Code, xmllint and Python

Notepad++ and VS Code do not format XML on their own: each needs a free extension, and then one shortcut does the job. xmllint and Python do it from a terminal or a script. Here are the menu paths, shortcuts and commands to format XML in Notepad++, VS Code, xmllint and Python, and the two Python traps that leave a file full of blank lines or not indented at all.

Which tool should you use to format XML?

The one you already have open. Formatting, also called pretty-printing, adds line breaks and indentation between elements. The data does not change, and a program that reads the file sees the same document. The four tools below give the same kind of result:

  • Notepad++ with the XML Tools plugin: Ctrl+Alt+Shift+B.
  • VS Code with the XML extension by Red Hat: Shift+Alt+F.
  • xmllint, on Linux, macOS or WSL: xmllint --format file.xml.
  • Python, for scripts that handle many files: minidom, ElementTree.indent() or lxml.

All of them need well-formed XML. If a tag is not closed, they refuse to format the file and point to a line number, which is where to start looking.

If you only want to read a file, you may not need to format it at all. Chrome indents XML by itself: open the XML file in Chrome and you get a tree, even when the file is one long line.

No editor at hand? Our free XML formatter indents a file in your browser, and the XML validator gives the line and column of the first error.

Format XML in Notepad++ with XML Tools

Notepad++ has no XML formatter of its own. The free XML Tools plugin adds one.

  1. Open Plugins > Plugins Admin.
  2. In the Available tab, search for “XML Tools”, tick it and click Install. Notepad++ restarts.
  3. Open your XML file, then choose Plugins > XML Tools > Pretty print, or press Ctrl+Alt+Shift+B.

The same menu has variants. Pretty print - indent attributes (Ctrl+Alt+Shift+A) also puts each attribute on its own line, which helps with long elements such as SVG paths or configuration entries. Pretty print - indent only fixes the indentation without adding line breaks. Linearize (Ctrl+Alt+Shift+L) does the reverse: it puts the whole document back on one line, which is handy before pasting XML into a test or a string.

If the shortcut seems to do nothing, run Plugins > XML Tools > Check XML syntax now. It reports the first error in the file. And if XML Tools is missing from Plugins Admin, its README describes the manual install: create an XMLTools folder in the plugins folder of Notepad++, copy XMLTools.dll into it, and restart.

Format XML in VS Code with the XML extension

VS Code formats JavaScript, TypeScript, JSON, HTML and CSS out of the box, but not XML. Run Format Document on an XML file without an extension, and VS Code tells you that no formatter is installed for XML files.

  1. Open the Extensions view (Ctrl+Shift+X), search for “XML” and install XML by Red Hat. Since version 0.15, it runs without Java.
  2. Open your file and press Shift+Alt+F on Windows, Shift+Option+F on macOS or Ctrl+Shift+I on Linux. Format Document is also in the Command Palette (Ctrl+Shift+P).
  3. To format only part of the file, select it and use Format Selection (Ctrl+K Ctrl+F).

If another installed extension also formats XML, VS Code asks which one to use. To make that choice permanent, set the indentation for XML only and format on every save, add this to your settings.json:

"[xml]": {
  "editor.defaultFormatter": "redhat.vscode-xml",
  "editor.tabSize": 2,
  "editor.formatOnSave": true
}

The Red Hat extension takes its indentation from editor.tabSize and editor.insertSpaces. Its own settings start with xml.format.: xml.format.splitAttributes decides whether attributes go on separate lines, and xml.format.maxLineWidth sets the maximum line width, 100 characters by default, or no limit with 0.

Format XML on the command line with xmllint

xmllint comes with libxml2. macOS ships it. On Debian and Ubuntu it is in the libxml2-utils package, and on Windows the easiest route is WSL with the same command:

sudo apt install libxml2-utils

Then:

xmllint --format input.xml                          # print the formatted XML
xmllint --format --output pretty.xml input.xml      # write it to a new file
curl -s https://example.com/sitemap.xml | xmllint --format -   # read from a pipe

Do not run xmllint --format file.xml > file.xml: the shell empties the file before xmllint reads it, and you lose it. Write to a new file, then rename it.

The indentation is two spaces by default. The XMLLINT_INDENT environment variable changes it:

XMLLINT_INDENT="    " xmllint --format input.xml   # four spaces
XMLLINT_INDENT=$'\t' xmllint --format input.xml    # tabs, in bash

--format drops the whitespace already present between elements before it indents again, so a file that was badly indented by hand comes out clean. When the XML is not well-formed, xmllint prints the file name, the line and the parser error, and exits with a non-zero code. That makes it a good check in a script or a CI job. To check a file without printing it, use xmllint --noout input.xml.

Pretty-print XML in Python: minidom, ElementTree and lxml

The quickest way in the standard library is xml.dom.minidom:

from xml.dom import minidom

dom = minidom.parse("input.xml")
print(dom.toprettyxml(indent="  "))

It has two traps. On a file that already has line breaks, toprettyxml() keeps the old whitespace and adds its own, so you get empty lines between elements. In our test with Python 3.14, a small indented file came out with blank lines around every child of the root. And without an encoding argument, the declaration it writes has no encoding: <?xml version="1.0" ?>. Pass encoding="UTF-8" to get bytes with the encoding declared.

Since Python 3.9, xml.etree.ElementTree.indent() avoids the first trap, because it replaces the whitespace between elements instead of adding to it:

import xml.etree.ElementTree as ET

tree = ET.parse("input.xml")
ET.indent(tree, space="  ")
tree.write("pretty.xml", encoding="UTF-8", xml_declaration=True)

With lxml (pip install lxml), pretty_print=True only indents elements that have no whitespace around them yet. The lxml FAQ explains why, and gives the fix: parse with remove_blank_text=True first.

from lxml import etree

parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse("input.xml", parser)
tree.write("pretty.xml", pretty_print=True, xml_declaration=True, encoding="UTF-8")

Without that parser option, our test file kept its one-line element as it was. lxml is also the library we used for server-side XSLT in Python, so a script that transforms files can format the result in the same pass.

Read a long XML file without reformatting it

Formatting is for editing and for clean diffs. To read a long file, a view that folds the structure is often faster than scrolling through thousands of indented lines, and it leaves the file untouched.

Chrome shows local and online XML files as an indented tree with no setup. XMLNest, an XML viewer for Chrome, available on the Chrome Web Store, adds folding, search in element names and values, a source view with line numbers, and the line and column of the error when a file is broken. That tells you where to look before you open the file in Notepad++ or VS Code to fix it.

Sources

  1. Notepad++ User Manual: Plugins (checked on 20 October 2026)
  2. XML Tools for Notepad++, README and menu source of morbac/xmltools on GitHub (checked on 20 October 2026)
  3. Visual Studio Code documentation: Basic editing, Formatting (checked on 20 October 2026)
  4. Visual Studio Marketplace: XML by Red Hat (checked on 20 October 2026)
  5. vscode-xml documentation: Formatting (checked on 20 October 2026)
  6. libxml2: xmllint manual page (checked on 20 October 2026)
  7. Debian packages: libxml2-utils (checked on 20 October 2026)
  8. Python documentation: xml.dom.minidom (checked on 20 October 2026)
  9. Python documentation: xml.etree.ElementTree, indent() (checked on 20 October 2026)
  10. lxml FAQ: Why doesn't the pretty_print option reformat my XML output? (checked on 20 October 2026)
  11. Test by XMLNest : Tested by XMLNest on 20 October 2026 with Python 3.14.3 and lxml 6.0.2, on a file whose root had one child element written on a single line under an existing indentation: minidom's toprettyxml(indent=" ") added blank lines around the child and wrote <?xml version="1.0" ?> with no encoding; ElementTree.indent() gave a clean two-space indentation; lxml with pretty_print=True left the child on one line, and indented it once the file was parsed with remove_blank_text=True (checked on 20 October 2026)