Skip to content

Instantly share code, notes, and snippets.

@DominicCronin
Last active June 4, 2024 13:40
Show Gist options
  • Save DominicCronin/62bcd1f1da993d64f35b16d78b35c3cc to your computer and use it in GitHub Desktop.
Save DominicCronin/62bcd1f1da993d64f35b16d78b35c3cc to your computer and use it in GitHub Desktop.
ValidateXmlFile: a powershell script for validating XML
function ValidateXmlFile {
param ([string]$xmlFile = $(read-host "Please specify the path to the Xml file"))
$xmlFile = resolve-path $xmlFile
"==============================================================="
"Validating $xmlFile using the schemas locations specified in it"
"==============================================================="
# The validating reader silently fails to catch any problems if the schema locations aren't set up properly
# So attempt to get to the right place....
pushd (Split-Path $xmlFile)
try {
$ns = @{xsi='http://www.w3.org/2001/XMLSchema-instance'}
# of course, if it's not well formed, it will barf here. Then we've also found a problem
# use * in the XPath because not all files begin with Configuration any more. We'll still
# assume the location is on the root element
$locationAttr = Select-Xml -Path $xmlFile -Namespace $ns -XPath */@xsi:noNamespaceSchemaLocation
if ($locationAttr -eq $null) {throw "Can't find schema location attribute. This ain't gonna work"}
$schemaLocation = resolve-path $locationAttr.Path
if ($schemaLocation -eq $null)
{
throw "Can't find schema at location specified in Xml file. Bailing"
}
$settings = new-object System.Xml.XmlReaderSettings
$settings.ValidationType = [System.Xml.ValidationType]::Schema
$settings.ValidationFlags = $settings.ValidationFlags `
-bor [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation
$handler = [System.Xml.Schema.ValidationEventHandler] {
$args = $_ # entering new block so copy $_
switch ($args.Severity) {
Error {
# Exception is an XmlSchemaException
Write-Host "ERROR: line $($args.Exception.LineNumber)" -nonewline
Write-Host " position $($args.Exception.LinePosition)"
Write-Host $args.Message
break
}
Warning {
# So far, everything that has caused the handler to fire, has caused an Error...
# So this /might/ be unreachable
Write-Host "Warning:: " + $args.Message
break
}
}
}
$settings.add_ValidationEventHandler($handler)
$reader = [System.Xml.XmlReader]::Create($xmlfile, $settings)
while($reader.Read()){}
$reader.Close()
}
catch {
throw
}
finally {
popd
}
}
@rokeno
Copy link

rokeno commented Jul 6, 2022

Doesn't actually work. I keep being thrown at line 16 due to the fact that the xmlFile path is empty.

@DominicCronin
Copy link
Author

Doesn't actually work. I keep being thrown at line 16 due to the fact that the xmlFile path is empty.

Hmm... I've used this a lot, although not recently. I suspect I've always passed a filename that actually exists. That said, I'd have expected it to fail at resolve-path if the file wasn't there. Are you sure the file is well-formed XML?

@r-pankevicius
Copy link

After like 47 add:

$settings.XmlResolver = new-object System.Xml.XmlUrlResolver

@DominicCronin
Copy link
Author

Hi r-pankevicius.

Thanks for the suggestion. Will that mean it can validate directly against schemas that are online?

Regards
Dominic

@r-pankevicius
Copy link

Well, not sure @DominicCronin what it helped with :)
I attempted to help my colleague to fix that and now I don't know exactly if that tweak I mentioned helped with it or colleague fixed schema urls.
Original goal was to validate XMLs against XSDs on local drive and the script didn't work for me. It just let valid XMLs to pass the validation against XSD: false positives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment