Skip to main content
added 59 characters in body
Source Link
CarlR
  • 1.8k
  • 1
  • 18
  • 21

Instead you should do validation while reading using an XmlReader and adding a validation event handler to a block of script.

Instead you should do validation while reading using an XmlReader.

Instead you should do validation while reading using an XmlReader and adding a validation event handler to a block of script.

Source Link
CarlR
  • 1.8k
  • 1
  • 18
  • 21

I realise this is an old question however I tried the answers provided and could not get them to work successfully in Powershell.

I have created the following function which uses some of the techniques described here. I have found it very reliable.

I had to validate XML documents before at various times however I always found the line number to be 0. It appears the XmlSchemaException.LineNumber will only be available while loading the document.

If you do validation afterwards using the Validate() method on an XmlDocument then LineNumber/LinePosition will always be 0.

Instead you should do validation while reading using an XmlReader.

Function Test-Xml()
{
    [CmdletBinding(PositionalBinding=$false)]
    param (
    [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
        [string] [ValidateScript({Test-Path -Path $_})] $Path,

        [Parameter(Mandatory=$true)]
        [string] [ValidateScript({Test-Path -Path $_})] $SchemaFilePath,

        [Parameter(Mandatory=$false)]
        $Namespace = $null
    )

    [string[]]$Script:XmlValidationErrorLog = @()
    [scriptblock] $ValidationEventHandler = {
        $Script:XmlValidationErrorLog += "`n" + "Line: $($_.Exception.LineNumber) Offset: $($_.Exception.LinePosition) - $($_.Message)"
    }

    $readerSettings = New-Object -TypeName System.Xml.XmlReaderSettings
    $readerSettings.ValidationType = [System.Xml.ValidationType]::Schema
    $readerSettings.ValidationFlags = [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessIdentityConstraints -bor
            [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation -bor 
            [System.Xml.Schema.XmlSchemaValidationFlags]::ReportValidationWarnings
    $readerSettings.Schemas.Add($Namespace, $SchemaFilePath) | Out-Null
    $readerSettings.add_ValidationEventHandler($ValidationEventHandler)
    try 
    {
        $reader = [System.Xml.XmlReader]::Create($Path, $readerSettings)
        while ($reader.Read()) { }
    }
    
    #handler to ensure we always close the reader sicne it locks files
    finally 
    {
        $reader.Close()
    }

    if ($Script:XmlValidationErrorLog) 
    {
        [string[]]$ValidationErrors = $Script:XmlValidationErrorLog
        Write-Warning "Xml file ""$Path"" is NOT valid according to schema ""$SchemaFilePath"""
        Write-Warning "$($Script:XmlValidationErrorLog.Count) errors found"
    }
    else 
    {
        Write-Host "Xml file ""$Path"" is valid according to schema ""$SchemaFilePath"""
    }

    Return ,$ValidationErrors #The comma prevents powershell from unravelling the collection http://bit.ly/1fcZovr
}