How do I use PowerShell to Validate XML files against an XSD?

前端 未结 8 1874
小鲜肉
小鲜肉 2020-12-05 02:26

As a part of my development I\'d like to be able to validate an entire folder\'s worth of XML files against a single XSD file. A PowerShell function seems like a good candid

相关标签:
8条回答
  • 2020-12-05 03:20

    The PowerShell Community Extensions has a Test-Xml cmdlet. The only downside is the extensions havn't been updated for awhile, but most do work on the lastest version of powershell (including Test-Xml). Just do a Get-Childitem's and pass the list to a foreach, calling Test-Xml on each.

    0 讨论(0)
  • 2020-12-05 03:25

    I re-wrote it (I know bad habbit) , but the starting script by @Flatliner_DOA was too good to discard completely.

    function Test-Xml {
    [cmdletbinding()]
    param(
        [parameter(mandatory=$true)]$InputFile,
        $Namespace = $null,
        [parameter(mandatory=$true)]$SchemaFile
    )
    
    BEGIN {
        $failCount = 0
        $failureMessages = ""
        $fileName = ""
    }
    
    PROCESS {
        if ($inputfile)
        {
            write-verbose "input file: $inputfile"
            write-verbose "schemafile: $SchemaFile"
            $fileName = (resolve-path $inputfile).path
            if (-not (test-path $SchemaFile)) {throw "schemafile not found $schemafile"}
            $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, $SchemaFile) | Out-Null
            $readerSettings.add_ValidationEventHandler(
            {
                try {
                    $detail = $_.Message 
                    $detail += "`n" + "On Line: $($_.exception.linenumber) Offset: $($_.exception.lineposition)"
                } catch {}
                $failureMessages += $detail
                $failCount = $failCount + 1
            });
            try {
                $reader = [System.Xml.XmlReader]::Create($fileName, $readerSettings)
                while ($reader.Read()) { }
            }
            #handler to ensure we always close the reader sicne it locks files
            finally {
                $reader.Close()
            }
        } else {
            throw 'no input file'
        }
    }
    
    END {
        if ($failureMessages)
        { $failureMessages}
        write-verbose "$failCount validation errors were found"
    
    }
    }
    
    #example calling/useage  code follows:
    $erroractionpreference = 'stop'
    Set-strictmode -version 2
    
    $valid = @(Test-Xml -inputfile $inputfile -schemafile $XSDPath )
    write-host "Found ($($valid.count)) errors"
    if ($valid.count) {
        $valid |write-host -foregroundcolor red
    }
    

    The function no longer pipelines as an alternative to using a file-path, it's a complication this use-case does not need. Feel free to hack the begin/process/end handlers away.

    0 讨论(0)
提交回复
热议问题