format-xml.ps1
<#PSScriptInfo .VERSION 1.2 .GUID d3735921-156b-4cd7-883f-d3cbaa0c5f81 .AUTHOR James O'Neill .COMPANYNAME Mobula Consulting Ltd .COPYRIGHT .TAGS .LICENSEURI https://opensource.org/licenses/MS-PL .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .DESCRIPTION Takes XML Text or paths to XML files and produces nicely indented output #> <# .SYNOPSIS Function to pretty-print XML .DESCRIPTION Takes XML Text or paths to XML files and produces nicely indented output .Parameter path Specifies the path to one or more XML files. .Parameter InputObject The text to format, or a file object which refers to an XML file Has an alias "Text", and accepts input via the pipe. .Example dir wl.* -recurse | Format-XML Finds one or matching files and outputs them as nicely indented XML .Example Format-XML .\wl.wml Does the same but with a known path .Example Invoke-WebRequest @parameters | format-xml Takes a set of pre-preared parameters which will return XML from a web service and formats the result. #> function Format-XML { Param ( [parameter(ValueFromPipelineByPropertyName=$true,ParameterSetName="Path",Mandatory=$true )][Alias('FullName')] $Path, [parameter(ValueFromPipeLine= $true,ParameterSetName="Pipe",Mandatory=$true, position=0)][Alias('Text')] $InputObject ) begin {#to cope with multiple items being piped we will assemble blocks of XML or Lumps of text in the process block and output them in the end block [xml[]]$xmlblocks = @() [String[]]$text = @() } process { #Catch file names; if text is not a file name assume it is going to be XML if (($InputObject -is [string]) -and ($null -eq $Path) -and (Test-Path -Path $InputObject -ErrorAction SilentlyContinue)) { $Path = $InputObject $InputObject = $null } #Read XML File(s) specified via $path if ($Path) { Resolve-Path -Path $Path -ErrorAction silentlycontinue | ForEach-Object { $xmlblocks += [xml](Get-Content -Path $_) } } #If input was a file object read XML from it elseif ($InputObject -is [System.IO.FileInfo]){ $doc = New-Object -TypeName System.Xml.XmlDataDocument $doc.Load($InputObject) $xmlblocks += $doc } #if input was already XML don't turn it back into text elseif ($InputObject -is [XML]) {$xmlblocks += $InputObject} #If input was text and not a path build up one big blok of text to convert at the end. else {$text += $InputObject} } end { #If the process block assembled something in $Text, convert it to XML if ($text) {$xmlblocks += [xml]$text } #And now output the XML blocks - we need a couple of objects $sw = New-Object -TypeName System.IO.StringWriter $writer = New-Object -TypeName System.Xml.XmlTextWriter -ArgumentList $sw -Property @{"Formatting" = [System.Xml.Formatting]::Indented } foreach ($doc in $xmlblocks) { $doc.WriteContentTo($writer) $sw.ToString() } } } |