Search code examples
xmllinuxformatcommand-line-interfacepretty-print

CLI tool to format XML files keeping empty lines and comments


Is there any CLI tool for Linux which formats XML files keeping any empty lines and comments? I have tried xmllint, tidy and xmlstarlet, but all seem to focus completely cleaning XML files rather than just indentation and spacing.


Solution

  • Try xmlindent. It has several options like -nbe and -nba and others that configure the handling of spaces before and after.

    Given an XML input of

    <?xml version="1.0"?>
    <Response>
      <TroubleResponse>
        <Check>
          <DStatus>
            <GID>123456789</GID>
            <FLAG/>
          </DStatus>
        </Check>
        <RAM>
          <Details>
            <RAMID>5555777788
            </RAMID>
          </Details>
        </RAM>
        <RAM>
          <Details>
            <RAMID>
                5555777788</RAMID>
          </Details>
        </RAM>
      </TroubleResponse>
    </Response>
    

    The output can be configured with the following options (an excerpt):

    -t     Use tabs instead of spaces
    -nas   Suppress newline after start-tag
    -nae   Suppress newline after end-tag
    -nbs   Suppress newline before start-tag
    -nbe   Suppress newline before end-tag
    -f     Force newline on elements without children
    

    So xmlindent -f and xmlindent -nba would produce the following output:

    <?xml version="1.0"?>
    <Response>
        <TroubleResponse>
            <Check>
                <DStatus>
                    <GID>123456789       <!-- Change -->
                    </GID>
                    <FLAG/>
                </DStatus>
            </Check>
            <RAM>
                <Details>
                    <RAMID>5555777788
                    </RAMID>
                </Details>
            </RAM>
            <RAM>
                <Details>
                    <RAMID>             <!-- Change -->
                        5555777788
                    </RAMID>
                </Details>
            </RAM>
        </TroubleResponse>
    </Response>
    

    And xmlindent -nbe would produce the following output:

    <?xml version="1.0"?>
    <Response>
        <TroubleResponse>
            <Check>
                <DStatus>
                    <GID>123456789</GID>
                    <FLAG/>
                </DStatus>
            </Check>
            <RAM>
                <Details>
                    <RAMID>5555777788
                    </RAMID>
                </Details>
            </RAM>
            <RAM>
                <Details>
                    <RAMID>                  <!-- Change -->
                    5555777788</RAMID>
                </Details>
            </RAM>
        </TroubleResponse>
    </Response>
    

    xmlindent is not perfect as it does not seem to always realize the expected outcome, but it can be somewhat configured.