Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a stylesheet or Windows commandline tool for controllable XML formatting, specifically putting attributes one-per-line?

I am searching for an XSLT or command-line tool (or C# code that can be made into a command-line tool, etc) for Windows that will do XML pretty-printing. Specifically, I want one that has the ability to put attributes one-to-a-line, something like:

<Node>
   <ChildNode 
      value1='5'
      value2='6'
      value3='happy' />
</Node>

It doesn't have to be EXACTLY like that, but I want to use it for an XML file that has nodes with dozens of attributes and spreading them across multiple lines makes them easier to read, edit, and text-diff.

NOTE: I think my preferred solution is an XSLT sheet I can pass through a C# method, though a Windows command-line tool is good too.

like image 904
Scott Stafford Avatar asked Apr 02 '10 18:04

Scott Stafford


2 Answers

Here's a PowerShell script to do it. It takes the following input:

<?xml version="1.0" encoding="utf-8"?>
<Node>
    <ChildNode value1="5" value2="6" value3="happy" />
</Node>

...and produces this as output:

<?xml version="1.0" encoding="utf-8"?>
<Node>
  <ChildNode
    value1="5"
    value2="6"
    value3="happy" />
</Node>

Here you go:

param(
    [string] $inputFile = $(throw "Please enter an input file name"),
    [string] $outputFile = $(throw "Please supply an output file name")
)

$data = [xml](Get-Content $inputFile)

$xws = new-object System.Xml.XmlWriterSettings
$xws.Indent = $true
$xws.IndentChars = "  "
$xws.NewLineOnAttributes = $true

$data.Save([Xml.XmlWriter]::Create($outputFile, $xws))

Take that script, save it as C:\formatxml.ps1. Then, from a PowerShell prompt type the following:

C:\formatxml.ps1 C:\Path\To\UglyFile.xml C:\Path\To\NeatAndTidyFile.xml

This script is basically just using the .NET framework so you could very easily migrate this into a C# application.

NOTE: If you have not run scripts from PowerShell before, you will have to execute the following command at an elevated PowerShell prompt before you will be able to execute the script:

Set-ExecutionPolicy RemoteSigned

You only have to do this one time though.

I hope that's useful to you.

like image 162
Damian Powell Avatar answered Sep 19 '22 09:09

Damian Powell


Here's a small C# sample, which can be used directly by your code, or built into an exe and called at the comand-line as "myexe from.xml to.xml":

    using System.Xml;

    static void Main(string[] args)
    {
        XmlWriterSettings settings = new XmlWriterSettings {
            NewLineHandling = NewLineHandling.Entitize,
            NewLineOnAttributes = true, Indent = true, IndentChars = "  ",
            NewLineChars = Environment.NewLine
        };

        using (XmlReader reader = XmlReader.Create(args[0]))
        using (XmlWriter writer = XmlWriter.Create(args[1], settings)) {
            writer.WriteNode(reader, false);
            writer.Close();
        }
    }

Sample input:

<Node><ChildNode value1='5' value2='6' value3='happy' /></Node>

Sample output (note you can remove the <?xml ... with settings.OmitXmlDeclaration):

<?xml version="1.0" encoding="utf-8"?>
<Node>
  <ChildNode
    value1="5"
    value2="6"
    value3="happy" />
</Node>

Note that if you want a string rather than write to a file, just swap with StringBuilder:

StringBuilder sb = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(oldXml)))
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
    writer.WriteNode(reader, false);
    writer.Close();
}
string newXml = sb.ToString();
like image 45
Marc Gravell Avatar answered Sep 18 '22 09:09

Marc Gravell