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 candidate for this as I can then just pipe a list of files to it like so: dir *.xml | Validate-Xml -Schema .\MySchema.xsd
I've considered porting C# code from the Validating an Xml against Referenced XSD in C# question, but I don't know how to Add handlers in PowerShell.
You can validate your XML documents against XML schemas only; validation against DTDs is not supported. However, although you cannot validate against DTDs, you can insert documents that contain a DOCTYPE or that refer to DTDs.
XML documents are validated by the Create method of the XmlReader class. To validate an XML document, construct an XmlReaderSettings object that contains an XML schema definition language (XSD) schema with which to validate the XML document. The System. Xml.
I want to comment that the script in current accepted answer doesn't validate errors about incorrect orders of elements of xs:sequence
. For example: test.xml
<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='test.xsd'> <address> <street>Baker street 5</street> <name>Joe Tester</name> </address> </addresses>
test.xsd
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'> <xs:element name="addresses"> <xs:complexType> <xs:sequence> <xs:element ref="address" minOccurs='1' maxOccurs='unbounded'/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="address"> <xs:complexType> <xs:sequence> <xs:element ref="name" minOccurs='0' maxOccurs='1'/> <xs:element ref="street" minOccurs='0' maxOccurs='1'/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="name" type='xs:string'/> <xs:element name="street" type='xs:string'/> </xs:schema>
I wrote another version that can report this error:
function Test-XmlFile { <# .Synopsis Validates an xml file against an xml schema file. .Example PS> dir *.xml | Test-XmlFile schema.xsd #> [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $SchemaFile, [Parameter(ValueFromPipeline=$true, Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [alias('Fullname')] [string] $XmlFile, [scriptblock] $ValidationEventHandler = { Write-Error $args[1].Exception } ) begin { $schemaReader = New-Object System.Xml.XmlTextReader $SchemaFile $schema = [System.Xml.Schema.XmlSchema]::Read($schemaReader, $ValidationEventHandler) } process { $ret = $true try { $xml = New-Object System.Xml.XmlDocument $xml.Schemas.Add($schema) | Out-Null $xml.Load($XmlFile) $xml.Validate({ throw ([PsCustomObject] @{ SchemaFile = $SchemaFile XmlFile = $XmlFile Exception = $args[1].Exception }) }) } catch { Write-Error $_ $ret = $false } $ret } end { $schemaReader.Close() } }
PS C:\temp\lab-xml-validation> dir test.xml | Test-XmlFile test.xsd
System.Xml.Schema.XmlSchemaValidationException: The element 'address' has invalid child element 'name'. ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With