【问题标题】:How to validate xml for correct syntax/format(?)如何验证 xml 的语法/格式是否正确(?)
【发布时间】:2013-01-03 15:14:59
【问题描述】:

假设我想在我的自定义工具箱模块中创建一个函数,该函数使用一些自定义 xml 文件来提供指令(使用 $xmlpath 参数传递)。如何确保输入使用正确的 xml 类型/语法/格式(正确的元素、根节点等)?我读过有关架构(xsd)和命名空间(不明白这一点)。

如果我使用模式文件:如何使用 ex.xml 验证 xml。测试 XML(PSCX cmdlet)?我是否在线存储 xsd 文件并在 xml 文档中指定它的路径?我是否将其存储在我的模块文件夹中并将其硬编码到脚本中?如果是这样,我如何指定模式路径?代码示例:

#Stored in ..\Modules\MyModule\Process-Config.psm1)
function Process-Config
{
    param($xmlpath)
    #Test that file is xml
    try{ $xml = [xml](Get-Content $xmlpath) } catch {}

    #Test that xml-file is valid against schema in Module-folder (Modules\MyModule\xmlschema.xsd)
    #Using Test-XML PSCX cmdlet
    Test-XML -Path $xmlpath -SchemaPath #Schemapath#

}

编辑:我发现 $PSScriptRoot 提供了模块位置,因此我可以使用 $PSScriptRoot\Schemas\MySchema.xsd 作为路径。我认为它只适用于脚本,但似乎功能也适用。 :-) 不过,我是否在 xml 中为这样的本地文件指定架构?如果是这样,我该如何指定这个本地路径,或者我应该也在线发布 xsd,以将其作为 xml 文件中的架构地址?

【问题讨论】:

    标签: xml powershell powershell-3.0


    【解决方案1】:

    我不太确定您是要检查 XML 有效性是作为程序的函数还是从服务的函数。

    首先,在 XML 中有很多东西要学,我找到了我正在研究的资源:@​​987654321@。您可能会发现这很有帮助。您不必一口气了解其中的所有内容。

    这是一个online service,它将检查 XML 文档的有效性。

    如果您希望程序能够做到这一点,我认为您需要某种 xml lint,可能类似于:xmlint

    最后,如果您想编写一个使用类似 API 的 xml lint 的程序,那么您应该指定您使用的编程语言。希望这会有帮助。干杯!

    【讨论】:

    • 感谢学习 xml 的链接,有时间会研究一下。我的意思是我希望 PS 中的 Cmdlet/函数在开始处理它之前验证它的输入(xml 文件的路径)。确保它包含 ex。车,不是书。这可以通过使用 ex 来完成。架构和一些 powerhsell/.net 代码(我已经看过代码),但是我如何为我的模块提供 XSD 文件。想象一下我的模块文件夹包含:mymodule.psm1、myxmslchema.xsd。如果我使用前。 Test-XML(PSCX cmdlet) 以针对架构对其进行测试。当我的模式路径驻留在模块文件夹中时,它将是什么?
    • 啊,我的错。我没有windows 8,所以我不太明白你所说的powershell是什么意思。现在我明白了,但如果没有进一步的研究,我不确定如何走得更远。干杯
    • :) 更新了问题以尝试使其更清晰。顺便说一句,powershell 可用于 XP 和 Vista ^^
    • 是的,我是 mac 和 linux 用户。我的妻子有 Vista,但我不经常使用它。
    【解决方案2】:

    这没有经过测试,但基于我编写的一个实用程序,用于检查 XML 与它声明使用的模式。它的核心是创建一个XmlReader,配置为执行基于 XSD 的验证并允许加载引用的架构。

    $readerSettings = New-Object 'System.Xml.XmlReaderSettings';
    $readerSettings.ValidationFlags = [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessInlineSchema -bor
                                      [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation -bor
                                      [System.Xml.Schema.XmlSchemaValidationFlags]::ReportValidationWarnings -bor
                                      [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessIdentityConstraints;
    $readerSettings.ValidationType = [System.Xml.ValidationType]::Schema;
    
    $results = @()
    
    $valHandler = [System.Xml.Schema.ValidationEventHandler]{
      # $_ is the second argument of type System.Xml.ValidationEventArgs
      $script:results += "{0}: {1}" -f $_.Severity, $_.Message;
    }
    
    $readerSettings.add_ValidationEventHandler($valHandler)
    
    $reader = [System.Xml.XmlReader]::Create($xmlFileName, $readerSettings);
    
    while ($reader.Read()) {
      # Do nothing...
    }
    
    $results;  # Return the array of validation errors and warnings.
    

    注意:

    • 在创建阅读器和处理 XML 时都会引发许多异常(例如,无效的 XML、找不到引用的架构)。
    • 可用的控件比此处显示的要多得多,阅读 XmlReaderSettingsValidationEventArgs 的文档(作为开始)会很有帮助。
    • 为文件指定架构 (XSD) 的常用方法是使用包含 {namespace, XSD-schmea} 对列表的 schemaLocation 属性(来自 http://www.w3.org/2001/XMLSchema-instance 命名空间)。不过XmlReaderSettings.Schemas 也可用于指定文档外的架构。

    【讨论】:

    • 这很好。它是否适用于 scehmalocation 中的本地路径?(例如“$PSScriptRoot\schema.xsd”)还是必须是在线地址。没有可以在 atm 上测试的计算机 :-)
    • @Graimer schemaLocation,如果我没记错的话,可以有相对于 XML 文档的路径(严格来说:到引用文档,因为一个 XSD 可以引用另一个 XSD(。它当然不能包含 PowerShell 变量(XML 不知道如何处理它们)。因此xsi:schemaLocation='urn:t-test:mydoc MySchema.xsd' 将引用与 XML 相同位置的架构。
    • 好吧。我想基思的回答更适合我。 +1 感谢您抽出宝贵时间。稍后也会找到这个的用途:)。顺便说一句,如果 schemalocation 是在线 URL,它会下载架构吗?
    • @Graimer:是的,它将从删除位置下载(除非选项 [System.Xml.XmlSchemaValidationFlags]::ProcessSchemaLocation 被删除)。还有XmlResolver 选项——一个能够接管将URN 转换为.NET 对象的自定义类(StreamXmlDocument、……可供 XML 解析器使用;但我认为实现一个是不可能的直接在 PSH 中)。
    【解决方案3】:

    指定 XSD 文件的文件路径,最好通过相对路径,除非 XSD 存储在您计划运行脚本的每台 PC 上的众所周知的路径中。对于相对路径,是的,使用 $PSScriptRoot 例如

    $xsd = $PSScriptRoot\schema.xsd
    Test-Xml -XmlPath $xmlPath -SchemaPath $xsd
    

    【讨论】:

    • 我需要在 xml 文件中指定 xsd 架构还是可选的?
    【解决方案4】:

    如果您想要对 XML 文件进行基本测试(无需验证 XML Schemata 或对外部模块的依赖),您可以使用function Test-XMLFile from Jonathan Medd

    function Test-XMLFile {
        <#
            .SYNOPSIS
            Test the validity of an XML file
        #>
        [CmdletBinding()]
        param (
            [parameter(mandatory=$true)][ValidateNotNullorEmpty()][string]$xmlFilePath
        )
    
        # Check the file exists
        if (!(Test-Path -Path $xmlFilePath)){
            throw "$xmlFilePath is not valid. Please provide a valid path to the .xml fileh"
        }
        # Check for Load or Parse errors when loading the XML file
        $xml = New-Object System.Xml.XmlDocument
        try {
            $xml.Load((Get-ChildItem -Path $xmlFilePath).FullName)
            return $true
        }
        catch [System.Xml.XmlException] {
            Write-Verbose "$xmlFilePath : $($_.toString())"
            return $false
        }
    }
    

    如果你想检查很多 XML 文件,你可以使用类似的东西

    gci -recurse *.xml |% {
     $outcome = Test-XMLFile $_.FullName -Verbose
    }
    

    这会告诉你哪个 XML 文件有什么问题。

    【讨论】:

      猜你喜欢
      • 2020-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      相关资源
      最近更新 更多