PowerShell ISE Addon: Validate and Format XML

by Ravikanth on May 30, 2012

I have been playing with XML documents a lot these days and at times I find myself dealing with a few pages long XML data. The most frustrating part is the un-formatted and invalid XML. Many times, I find myself dealing with XML errors than any script errors. Fortunately, PowerShell ISE in version 3.0 provides, XML syntax checks.

But, here is the catch:

These syntax checks work only with saved files and only if the file name ends with .xml. Also, it is quite possible to overlook these errors in an XML document that is a few hundred lines long. Also, there is no way to easily and automatically indent a XML document.

So, here is another addon to make life easy when using XML documents in PowerShell ISE. This addon actually comes with a couple of functions.

Update: Updated the post to include support for selected text. Now, you can select an XML snippet in your script and then validate it or format it.

Here is quick video that shows how this addon works:

Validating XML content

I used the C# sample available on this MSDN pageto build the PowerShell script for validating XML document. This is not complete yet. It can only verify if all required tags are in place or not and does not compare the XML data against any schema definition you have.

#Source: C# implementation at http://msdn.microsoft.com/en-us/library/system.xml.schema.validationeventargs.severity.aspx
function Test-XML {
    Param (
        [string]$xmlPath
    )

    $xmlReaderConfig = new-object System.Xml.XmlReaderSettings
    $xmlReaderConfig.ValidationType = [System.Xml.ValidationType]::Schema
    $xmlReaderConfig.ValidationFlags = $xmlReader.ValidationFlags -bor [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation
    $eventhandler = [System.Xml.Schema.ValidationEventHandler] {
        switch ($_.Severity) {
            Error {
                $_.Message
                break
            }
        }
    }
    $xmlReaderConfig.add_ValidationEventHandler($eventhandler)
    $xmlReader = [System.Xml.XmlReader]::Create($xmlPath, $xmlReaderConfig)
    while($xmlReader.Read()){}
    if ($?) {
        $xmlReader.Close()
        return $true
    } else {
        $xmlReader.Close()
        return $false
    }
}

Formatting the XML content

#Source: Windows PowerShell Team Blog
function Format-XML
{
    param (
        [xml]$xml,
        $indent = 4
    )

    $StringWriter = New-Object System.IO.StringWriter
    $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
    $xmlWriter.Formatting = "indented"
    $xmlWriter.Indentation = $Indent
    $xml.WriteContentTo($XmlWriter)
    $XmlWriter.Flush()
    $StringWriter.Flush()
    return $StringWriter.ToString()
}

This function returns the formatted XML output. Thanks to the PowerShell team for this pointer. I did not really have to write anything myself for formatting XML. Now, I added these two to my ISE profile and created addon menus that use these functions.

$validateBlock = {
    if ($psISE.CurrentFile.Editor.SelectedText) {
        $filePath = "${Env:Temp}\temp.xml"
        Set-Content -PassThru $filePath -Value $psISE.CurrentFile.Editor.SelectedText
        $cleanUp = $true
    } else {
        if ($psISE.CurrentFile.IsSaved) {
            $filePath = $psISE.CurrentFile.FullPath
        } else {
            $filePath = "${Env:Temp}\temp.xml"
            Set-Content -PassThru $filePath -Value $psISE.CurrentFile.Editor.Text
            $cleanUp = $true
        }
    }

    if (Test-XML $filePath) {
        [System.Windows.Forms.MessageBox]::Show("XML document is valid.")
    } else {
        [System.Windows.Forms.MessageBox]::Show("Invalid XML document. Refer to console output!")
    }

    if ($cleanUp) {
        Remove-Item -Path "${Env:Temp}\temp.xml" -Force
        $cleanUp = $false
    }
}

$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Validate _XML",$validateBlock,"Ctrl+Alt+X")

$formatBlock = {
    if ($psISE.CurrentFile.Editor.SelectedText) {
        $filePath = "${Env:Temp}\temp.xml"
        Set-Content -PassThru $filePath -Value $psISE.CurrentFile.Editor.SelectedText
        $cleanUp = $true
    } else {
        if ($psISE.CurrentFile.IsSaved) {
            $filePath = $psISE.CurrentFile.FullPath
        } else {
            $filePath = "${Env:Temp}\temp.xml"
            Set-Content -PassThru $filePath -Value $psISE.CurrentFile.Editor.Text
            $cleanUp = $true
        }
    }

    if (Test-XML $filePath) {
        $psISE.CurrentFile.Editor.Text = Format-XML (Get-Content $filePath)
    } else {
        [System.Windows.Forms.MessageBox]::Show("Invalid XML document. Refer to console output!")
    }

    if ($cleanUp) {
        Remove-Item -Path "${Env:Temp}\temp.xml" -Force
        $cleanUp = $false
    }
}

$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Format _XML",$formatBlock,"Alt+X")

This is it. Now, whenever I need to validate XML content, I can simply press Ctrl+Alt+X and Alt+X, when I want to format the XML document.

Ravikanth

A technology enthu and a Windows PowerShell MVP working on SharePoint solutions at Dell Inc. Has deep interests in Windows Server OS & Virtualization.

More Posts - Website - Twitter - Facebook

Previous post:

Next post: