J'utilise Powershell pour valider plusieurs fichiers XML par rapport à plusieurs XSD. Cette partie du code fonctionne comme prévu, mais je dois également déplacer tout fichier XML qui ne parvient pas à être validé vers un dossier "Invalide". J'essaie de parcourir ces fichiers en boucle à l'aide de ForEach, puis, à l'aide d'une instruction If, de déplacer tout fichier ayant échoué. Le problème est que tous les fichiers sont déplacés, qu'ils aient échoué ou non.
J'ai écrit cette boucle de toutes les manières possibles et imaginables, mais je n'obtiens pas le résultat escompté. (J'ai également parcouru le Web pendant des jours pour trouver la réponse.) J'ai besoin que ForEach applique le code à chaque fichier, un par un. S'agit-il d'un problème de syntaxe ? Peut-être que quelque chose de très évident m'échappe, mais je ne sais plus où j'en suis.
J'utilise cette fonction (trouvée sur Stack Overflow, et comme indiqué ici, légèrement modifiée) pour valider les XML.
function Test-XmlFile
{
<#
.Synopsis
Validates an xml file against an xml schema file.
.Example
PS> dir *.xml | Test-XmlFile schema.xsd
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline=$true, Mandatory=$true)]
[SupportsWildcards()]
$SchemaFile,
[Parameter(ValueFromPipeline=$true, Mandatory=$true)]
[SupportsWildcards()]
[alias('Fullname')]
$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()
}
}
Et voici comment je sélectionne les XML pour les valider par rapport à leurs schémas respectifs.
$allfiles = "..\Schema Validation\XMLs\*.xml"
$xml1 = Get-ChildItem $allfiles -Recurse | Select-String "<UniqueElement>" -List | Resolve-Path
$xml2 = Get-ChildItem $allfiles -Recurse | Select-String "<UniqueElement>" -List | Resolve-Path
$xsd1 = "..\Schema Validation\Schemas\Schema1.xsd"
$xsd2 = "..\Schema Validation\Schemas\Schema2.xsd"
Et voici la boucle ForEach qui ne fonctionne pas pour moi. (Dans sa configuration actuelle, bien que je l'aie écrite d'une douzaine de façons différentes).
ForEach ($xml in $xml1) {
$xml | Test-XmlFile $xsd1
If ($Error) {
$Error[0].Exception, "`r" | Out-File "..\Schema Validation\Results\log.txt"
Move-Item $xml -Destination "..\Schema Validation\Invalid"
}}
La boucle ForEach ci-dessus est également répétée pour les variables $xml2 et $xsd2. (Et comme vous pouvez le voir dans le fichier de sortie, je capture également le message d'exception dans un fichier texte pour une sorte de journal).
Je m'attendais à ce que seuls les XML présentant une erreur et une exception soient déplacés, en raison de l'instruction " If ($Error) " et du fait que j'essaie de parcourir les fichiers un par un ; or, ce qui se passe, c'est que tout XML contenant la chaîne unique qui l'identifie comme faisant partie du groupe $xml1 ou $xml2 est déplacé vers le dossier Invalid, erreur ou pas. Alors quelle est la chose douloureusement évidente que j'ai manquée ? (Incidemment, le texte de l'exception alimente le journal des erreurs comme prévu, donc au moins cette partie fonctionne comme je l'espérais).
EDIT : En y réfléchissant, je ne devrais pas dire que le texte d'exception remplit le journal "comme prévu". Il remplit le journal, mais il écrit le message dans le fichier journal une fois pour chaque fichier inclus dans la variable (chaque fichier dans $xml1, par exemple), que le fichier ait erré ou non. Ainsi, s'il y a deux fichiers dans $xml1, mais qu'un seul est invalide, le message d'exception unique pour ce seul fichier invalide sera écrit deux fois dans le journal. Donc, il écrit quelque chose pour chaque fichier qui est bouclé, indépendamment de la validité ou des erreurs. J'espère que cela a du sens.