PowerShell을 사용하여 XSD에 대해 XML 파일의 유효성을 검사하는 방법은 무엇입니까?
개발 과정에서 단일 XSD 파일에 대해 전체 폴더의 XML 파일 가치를 확인할 수 있습니다.PowerShell 함수는 다음과 같이 파일 목록을 파이프로 연결할 수 있기 때문에 적합한 후보로 보입니다. dir *.xml | Validate-Xml -Schema.\MySchema.xsd
C#의 참조된 XSD에 대한 Xml 유효성 검사 문제에서 C# 코드를 이식하는 것을 고려했지만 PowerShell에서 핸들러를 추가하는 방법을 모르겠습니다.
현재 승인된 답변의 스크립트가 다음 요소의 잘못된 순서에 대한 오류를 검증하지 않는다는 점에 대해 언급하고 싶습니다.xs:sequence
예: 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>
이 오류를 보고할 수 있는 다른 버전을 작성했습니다.
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()
}
}
PSC:\temp\lab-xml-validation> dir test.xml | Test-XmlFile 테스트.xsd
System.Xml.Schema.XmlSchemaValidationException: The element 'address' has invalid child element 'name'.
...
PowerShell Community Extensions에는 Test-Xml cmdlet이 있습니다.유일한 단점은 확장이 한동안 업데이트되지 않았다는 것이지만 대부분의 경우 파워셸의 최신 버전(Test-Xml 포함)에서 작동한다는 것입니다.Get-Child 항목을 수행하고 각 항목에 대해 목록을 전달하고 각 항목에 대해 Test-Xml을 호출합니다.
이를 위해 PowerShell 함수를 작성했습니다.
용도:
dir *.xml | 테스트-Xml - 스키마 ".\MySchemaFile.xsd" - 네임스페이스 "http://tempuri.org "
코드:
function Test-Xml {
param(
$InputObject = $null,
$Namespace = $null,
$SchemaFile = $null
)
BEGIN {
$failCount = 0
$failureMessages = ""
$fileName = ""
}
PROCESS {
if ($InputObject -and $_) {
throw 'ParameterBinderStrings\AmbiguousParameterSet'
break
} elseif ($InputObject) {
$InputObject
} elseif ($_) {
$fileName = $_.FullName
$readerSettings = New-Object -TypeName System.Xml.XmlReaderSettings
$readerSettings.ValidationType = [System.Xml.ValidationType]::Schema
$readerSettings.ValidationFlags = [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessInlineSchema -bor
[System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation -bor
[System.Xml.Schema.XmlSchemaValidationFlags]::ReportValidationWarnings
$readerSettings.Schemas.Add($Namespace, $SchemaFile) | Out-Null
$readerSettings.add_ValidationEventHandler(
{
$failureMessages = $failureMessages + [System.Environment]::NewLine + $fileName + " - " + $_.Message
$failCount = $failCount + 1
});
$reader = [System.Xml.XmlReader]::Create($_, $readerSettings)
while ($reader.Read()) { }
$reader.Close()
} else {
throw 'ParameterBinderStrings\InputObjectNotBound'
}
}
END {
$failureMessages
"$failCount validation errors were found"
}
}
저는 이 간단한 스니펫을 사용하고 있으며, 항상 작동하며 복잡한 기능이 필요하지 않습니다.이 예에서는 나중에 배포 및 서버 구성에 사용되는 데이터가 포함된 구성 xml을 로드합니다.
# You probably don't need this, it's just my way
$script:Context = New-Object -TypeName System.Management.Automation.PSObject
Add-Member -InputObject $Context -MemberType NoteProperty -Name Configuration -Value ""
$ConfigurationPath = $(Join-Path -Path $PWD -ChildPath "Configuration")
# Load xml and its schema
$Context.Configuration = [xml](Get-Content -LiteralPath $(Join-Path -Path $ConfigurationPath -ChildPath "Configuration.xml"))
$Context.Configuration.Schemas.Add($null, $(Join-Path -Path $ConfigurationPath -ChildPath "Configuration.xsd")) | Out-Null
# Validate xml against schema
$Context.Configuration.Validate(
{
Write-Host "ERROR: The Configuration-File Configuration.xml is not valid. $($_.Message)" -ForegroundColor Red
exit 1
})
(Flatliner DOA)의 솔루션은 PSv2에서는 잘 작동하지만 Server 2012 PSv3에서는 잘 작동하지 않습니다.
(wangzq)의 솔루션은 PS2와 PS3에서 작동합니다!!
PS3에서 xml 검증이 필요한 사람은 누구나 이것을 사용할 수 있습니다(wangzq의 기능에 기반).
function Test-Xml {
param (
[Parameter(ValueFromPipeline=$true, Mandatory=$true)]
[string] $XmlFile,
[Parameter(Mandatory=$true)]
[string] $SchemaFile
)
[string[]]$Script:XmlValidationErrorLog = @()
[scriptblock] $ValidationEventHandler = {
$Script:XmlValidationErrorLog += $args[1].Exception.Message
}
$xml = New-Object System.Xml.XmlDocument
$schemaReader = New-Object System.Xml.XmlTextReader $SchemaFile
$schema = [System.Xml.Schema.XmlSchema]::Read($schemaReader, $ValidationEventHandler)
$xml.Schemas.Add($schema) | Out-Null
$xml.Load($XmlFile)
$xml.Validate($ValidationEventHandler)
if ($Script:XmlValidationErrorLog) {
Write-Warning "$($Script:XmlValidationErrorLog.Count) errors found"
Write-Error "$Script:XmlValidationErrorLog"
}
else {
Write-Host "The script is valid"
}
}
Test-Xml -XmlFile $XmlFile -SchemaFile $SchemaFile
인라인 스키마 참조를 사용하여 XML 파일에 대해 XSD 유효성 검사를 수행할 수 있는 별도의 PowerShell 파일을 만들었습니다.정말 잘 작동합니다.다운로드 및 방법은 https://knowledge.zomers.eu/PowerShell/Pages/How-to-validate-XML-against-an-XSD-schema-using-PowerShell.aspx 에서 확인할 수 있습니다.
저는 이것이 오래된 질문이라는 것을 알지만 제공된 답변을 시도했지만 파워셸에서 성공적으로 작동할 수 없었습니다.
여기에 설명된 몇 가지 기술을 사용하여 다음과 같은 기능을 만들었습니다.저는 그것이 매우 믿을 만하다는 것을 알았습니다.
이전에는 XML 문서의 유효성을 여러 번 확인해야 했지만 항상 라인 번호가 0입니다.다음과 같이 나타납니다.XmlSchemaException.LineNumber
문서를 로드하는 동안에만 사용할 수 있습니다.
에 나에를사유여경검효수사우행는하를중성을 합니다.Validate()
에 있는 .XmlDocument
라인 번호/라인 위치는 0입니다.
대신에, 당신은 읽는 동안 유효성 검사를 해야 합니다.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
}
다시 썼지만(나쁜 습관은 알아요) @Flatliner_의 시작 스크립트DOA는 너무 좋아서 완전히 버릴 수 없었습니다.
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
}
이 기능은 더 이상 파일 경로를 사용하는 대신 파이프라인을 사용하지 않으며, 이 사용 사례에서 필요로 하지 않는 복잡성입니다.시작/프로세스/종료 핸들러를 자유롭게 해킹할 수 있습니다.
언급URL : https://stackoverflow.com/questions/822907/how-do-i-use-powershell-to-validate-xml-files-against-an-xsd
'programing' 카테고리의 다른 글
SQLSTATE[42000]:구문 오류 또는 액세스 위반: 마이그레이션에서 Laravel 및 MariaDB 오류 1064 (0) | 2023.08.25 |
---|---|
ORA-01735: 잘못된 ALTER TABLE 옵션 - Toad (0) | 2023.08.25 |
숫자 키패드의 keyCode 값? (0) | 2023.08.25 |
내 MariaDB SQL 쿼리가 INT를 VARCHAR로 정렬하는 이유는 무엇입니까? (0) | 2023.08.25 |
ApplicationContext 개체에서 속성 값을 가져오려면 어떻게 해야 합니까?(주석 사용 안 함) (0) | 2023.08.25 |