为什么我使用 System.Xml.XmlReader 的代码没有检测到无效的 XML 文件?
Why doesn't my code that uses System.Xml.XmlReader detect an invalid XML file?
目标
使用 PowerShell 5.1,通过使用 Microsoft 的 System.Xml.XmlReader
根据 XML 模式对其进行验证来检测无效的 XML 文件。我将通过捕获 XmlReader
在 XML 解析错误时抛出的 XMLException
来检测无效的 XML 文件。
注意:我不想使用 PowerShell 社区扩展 Test-Xml
cmdlet。
问题
代码行 $readerResult = $xmlReader.Read()
在解析无效的 XML 文件时没有抛出我期望的 XML 异常
参考资料
Validation Using the XmlSchemaSet
我的XSD
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:config-file-schema">
<xs:element name="notes">
<xs:complexType>
<xs:sequence>
<xs:element name="note" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="to"/>
<xs:element name="from">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:byte" name="type" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="heading"/>
<xs:element type="xs:string" name="body"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我的无效XML(第二行使用了伪造的元素名称notXXXes
)
<?xml version="1.0" encoding="UTF-8"?>
<notXXXes xmlns="urn:config-file-schema">
<note>
<to>Tove</to>
<from type="1">Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note>
<to>Bob</to>
<from type="2">KeyW</from>
<heading>Reminder</heading>
<body>I won't</body>
</note>
</notes>
我的代码
当运行、$readerResult
、returns为真时,说明下一个节点读取成功。我希望 $xmlReader.Read()
抛出一个 XMLException
因为 XML 文件内容违反了架构。
cls
$error.clear()
try
{
[System.Xml.Schema.XmlSchemaSet] $schemaSet = New-Object -TypeName System.Xml.Schema.XmlSchemaSet
$schemaSet.Add("urn:config-file-schema","C:\Users\x\Desktop\test.xsd");
[System.Xml.XmlReaderSettings] $readerSettings = New-Object -TypeName System.Xml.XmlReaderSettings
$readerSettings.Schemas = $schemaSet
$readerSettings.ValidationType = [System.Xml.ValidationType]::Schema
$readerSettings.ConformanceLevel = [System.Xml.ConformanceLevel]::Fragment
$readerSettings.IgnoreWhitespace = $true;
$readerSettings.IgnoreComments = $true;
[System.Xml.XmlReader]$xmlReader = [System.Xml.XmlReader]::Create("C:\Users\x\Desktop\test.xml", $readerSettings);
#just to show that Schemas was set up OK
"target namespace: " + $readerSettings.Schemas.Schemas().TargetNamespace
$readerResult = $xmlReader.Read()
"readerResult: " + $readerResult
}
catch
{
"error: " + $error
}
finally
{
$xmlReader.Close()
}
编辑#1
此片段将从文件中读取 XML 的每一行并显示其元数据
while ($xmlReader.Read())
{
write-console ("Depth:{0,1} Name:{1,-10} NodeType:{2,-15} Value:{3,-30}" -f $xmlReader.Depth, $xmlReader.Name, $xmlReader.NodeType, $xmlReader.Value)
}
XmlReader
概念的全部意义在于它是一种 流式处理 处理 XML 的方法。这允许您访问 large/complex XML 文档而不必将整个内容保存在内存中(并且,如果您使用 DOM 样式的访问,则需要使用几层额外的内存来启动).
这在内存使用方面是高效的,但确实意味着只有在遇到问题的节点时才会报告错误。
这里的第一个 Read
是 XML 声明 - <?xml version="1.0" encoding="UTF-8"?>
- 它看起来格式正确,不应引发任何错误。如果您需要验证整个文档,那么您需要 Read
完整地验证它直到最后。但如果那是你的 only 目的,我可能会推迟,例如您要关闭的 Test-Xml
commandlet。
目标
使用 PowerShell 5.1,通过使用 Microsoft 的 System.Xml.XmlReader
根据 XML 模式对其进行验证来检测无效的 XML 文件。我将通过捕获 XmlReader
在 XML 解析错误时抛出的 XMLException
来检测无效的 XML 文件。
注意:我不想使用 PowerShell 社区扩展 Test-Xml
cmdlet。
问题
代码行 $readerResult = $xmlReader.Read()
在解析无效的 XML 文件时没有抛出我期望的 XML 异常
参考资料
Validation Using the XmlSchemaSet
我的XSD
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:config-file-schema">
<xs:element name="notes">
<xs:complexType>
<xs:sequence>
<xs:element name="note" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="to"/>
<xs:element name="from">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:byte" name="type" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="heading"/>
<xs:element type="xs:string" name="body"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我的无效XML(第二行使用了伪造的元素名称notXXXes
)
<?xml version="1.0" encoding="UTF-8"?>
<notXXXes xmlns="urn:config-file-schema">
<note>
<to>Tove</to>
<from type="1">Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note>
<to>Bob</to>
<from type="2">KeyW</from>
<heading>Reminder</heading>
<body>I won't</body>
</note>
</notes>
我的代码
当运行、$readerResult
、returns为真时,说明下一个节点读取成功。我希望 $xmlReader.Read()
抛出一个 XMLException
因为 XML 文件内容违反了架构。
cls
$error.clear()
try
{
[System.Xml.Schema.XmlSchemaSet] $schemaSet = New-Object -TypeName System.Xml.Schema.XmlSchemaSet
$schemaSet.Add("urn:config-file-schema","C:\Users\x\Desktop\test.xsd");
[System.Xml.XmlReaderSettings] $readerSettings = New-Object -TypeName System.Xml.XmlReaderSettings
$readerSettings.Schemas = $schemaSet
$readerSettings.ValidationType = [System.Xml.ValidationType]::Schema
$readerSettings.ConformanceLevel = [System.Xml.ConformanceLevel]::Fragment
$readerSettings.IgnoreWhitespace = $true;
$readerSettings.IgnoreComments = $true;
[System.Xml.XmlReader]$xmlReader = [System.Xml.XmlReader]::Create("C:\Users\x\Desktop\test.xml", $readerSettings);
#just to show that Schemas was set up OK
"target namespace: " + $readerSettings.Schemas.Schemas().TargetNamespace
$readerResult = $xmlReader.Read()
"readerResult: " + $readerResult
}
catch
{
"error: " + $error
}
finally
{
$xmlReader.Close()
}
编辑#1
此片段将从文件中读取 XML 的每一行并显示其元数据
while ($xmlReader.Read())
{
write-console ("Depth:{0,1} Name:{1,-10} NodeType:{2,-15} Value:{3,-30}" -f $xmlReader.Depth, $xmlReader.Name, $xmlReader.NodeType, $xmlReader.Value)
}
XmlReader
概念的全部意义在于它是一种 流式处理 处理 XML 的方法。这允许您访问 large/complex XML 文档而不必将整个内容保存在内存中(并且,如果您使用 DOM 样式的访问,则需要使用几层额外的内存来启动).
这在内存使用方面是高效的,但确实意味着只有在遇到问题的节点时才会报告错误。
这里的第一个 Read
是 XML 声明 - <?xml version="1.0" encoding="UTF-8"?>
- 它看起来格式正确,不应引发任何错误。如果您需要验证整个文档,那么您需要 Read
完整地验证它直到最后。但如果那是你的 only 目的,我可能会推迟,例如您要关闭的 Test-Xml
commandlet。