驗證 DOM 中的 XML 檔
根據預設,XmlDocument 類別不會根據 XML 架構定義語言 (XSD) 架構或檔案類型定義 (DTD) 來驗證檔案物件模型 (DOM) 中的 XML;XML 只會驗證為格式正確的 。
若要驗證 DOM 中的 XML,您可以將架構驗證 XmlReader 傳遞至 XmlDocument 類別的 Load 方法,或使用 XmlDocument 類別的 Validate 方法驗證 DOM 中先前未驗證的 XML 檔,以驗證該 XML 載入 DOM。
將 XML 檔載入 DOM 時驗證
當將驗證的 XmlReader 傳遞給 XmlDocument 類別的 Load 方法時,XmlDocument 類別會在 XML 數據載入 DOM 的過程中驗證該數據。
成功驗證之後,會套用架構預設值,視需要將文字值轉換成原子值,並將類型資訊與已驗證的資訊項目相關聯。 因此,具類型的 XML 資料會取代先前不具類型的 XML 數據。
建立 XML Schema-Validating XmlReader
若要建立 XML 架構驗證 XmlReader,請遵循下列步驟。
建構新的 XmlReaderSettings 實例。
將 XML 架構新增至 XmlReaderSettings 實例的 Schemas 屬性。
將
Schema
指定為 ValidationType。選擇性地指定 ValidationFlags 和 ValidationEventHandler,以處理驗證期間遇到的架構驗證錯誤和警告。
最後,將 XmlReaderSettings 物件傳遞至 XmlReader 類別的 Create 方法,以及 XML 檔,建立架構驗證 XmlReader。
範例
在下列程式代碼範例中,架構驗證 XmlReader 會驗證載入 DOM 中的 XML 數據。 對 XML 檔進行無效的修改,然後重新驗證檔,導致架構驗證錯誤。 最後,修正了一個錯誤,接著對 XML 文件的一部分進行部分驗證。
#using <System.Xml.dll>
using namespace System;
using namespace System::Xml;
using namespace System::Xml::Schema;
ref class XmlDocumentValidationExample
{
public:
static void Main()
{
try
{
// Create a schema validating XmlReader.
XmlReaderSettings^ settings = gcnew XmlReaderSettings();
settings->Schemas->Add("http://www.contoso.com/books", "contosoBooks.xsd");
ValidationEventHandler^ eventHandler = gcnew ValidationEventHandler(ValidationEventHandlerOne);
settings->ValidationEventHandler += eventHandler;
settings->ValidationFlags = settings->ValidationFlags | XmlSchemaValidationFlags::ReportValidationWarnings;
settings->ValidationType = ValidationType::Schema;
XmlReader^ reader = XmlReader::Create("contosoBooks.xml", settings);
// The XmlDocument validates the XML document contained
// in the XmlReader as it is loaded into the DOM.
XmlDocument^ document = gcnew XmlDocument();
document->Load(reader);
// Make an invalid change to the first and last
// price elements in the XML document, and write
// the XmlSchemaInfo values assigned to the price
// element during load validation to the console.
XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(document->NameTable);
manager->AddNamespace("bk", "http://www.contoso.com/books");
XmlNode^ priceNode = document->SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager);
Console::WriteLine("SchemaInfo.IsDefault: {0}", priceNode->SchemaInfo->IsDefault);
Console::WriteLine("SchemaInfo.IsNil: {0}", priceNode->SchemaInfo->IsNil);
Console::WriteLine("SchemaInfo.SchemaElement: {0}", priceNode->SchemaInfo->SchemaElement);
Console::WriteLine("SchemaInfo.SchemaType: {0}", priceNode->SchemaInfo->SchemaType);
Console::WriteLine("SchemaInfo.Validity: {0}", priceNode->SchemaInfo->Validity);
priceNode->InnerXml = "A";
XmlNodeList^ priceNodes = document->SelectNodes("/bk:bookstore/bk:book/bk:price", manager);
XmlNode^ lastprice = priceNodes[priceNodes->Count - 1];
lastprice->InnerXml = "B";
// Validate the XML document with the invalid changes.
// The invalid changes cause schema validation errors.
document->Validate(eventHandler);
// Correct the invalid change to the first price element.
priceNode->InnerXml = "8.99";
// Validate only the first book element. The last book
// element is invalid, but not included in validation.
XmlNode^ bookNode = document->SelectSingleNode("/bk:bookstore/bk:book", manager);
document->Validate(eventHandler, bookNode);
}
catch (XmlException^ ex)
{
Console::WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex->Message);
}
catch(XmlSchemaValidationException^ ex)
{
Console::WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex->Message);
}
catch (Exception^ ex)
{
Console::WriteLine("XmlDocumentValidationExample.Exception: {0}", ex->Message);
}
}
static void ValidationEventHandlerOne(Object^ sender, ValidationEventArgs^ args)
{
if (args->Severity == XmlSeverityType::Warning)
Console::Write("\nWARNING: ");
else if (args->Severity == XmlSeverityType::Error)
Console::Write("\nERROR: ");
Console::WriteLine(args->Message);
}
};
int main()
{
XmlDocumentValidationExample::Main();
return 0;
}
using System;
using System.Xml;
using System.Xml.Schema;
class XmlDocumentValidationExample
{
static void Main(string[] args)
{
try
{
// Create a schema validating XmlReader.
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
// The XmlDocument validates the XML document contained
// in the XmlReader as it is loaded into the DOM.
XmlDocument document = new XmlDocument();
document.Load(reader);
// Make an invalid change to the first and last
// price elements in the XML document, and write
// the XmlSchemaInfo values assigned to the price
// element during load validation to the console.
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);
Console.WriteLine($"SchemaInfo.IsDefault: {priceNode.SchemaInfo.IsDefault}");
Console.WriteLine($"SchemaInfo.IsNil: {priceNode.SchemaInfo.IsNil}");
Console.WriteLine($"SchemaInfo.SchemaElement: {priceNode.SchemaInfo.SchemaElement}");
Console.WriteLine($"SchemaInfo.SchemaType: {priceNode.SchemaInfo.SchemaType}");
Console.WriteLine($"SchemaInfo.Validity: {priceNode.SchemaInfo.Validity}");
priceNode.InnerXml = "A";
XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
XmlNode lastprice = priceNodes[priceNodes.Count - 1];
lastprice.InnerXml = "B";
// Validate the XML document with the invalid changes.
// The invalid changes cause schema validation errors.
document.Validate(ValidationEventHandler);
// Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99";
// Validate only the first book element. The last book
// element is invalid, but not included in validation.
XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
document.Validate(ValidationEventHandler, bookNode);
}
catch (XmlException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlException: {ex.Message}");
}
catch(XmlSchemaValidationException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlSchemaValidationException: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"XmlDocumentValidationExample.Exception: {ex.Message}");
}
}
static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("\nWARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("\nERROR: ");
Console.WriteLine(args.Message);
}
}
Imports System.Xml
Imports System.Xml.Schema
Class XmlDocumentValidationExample
Shared Sub Main()
Try
' Create a schema validating XmlReader.
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
AddHandler settings.ValidationEventHandler, New ValidationEventHandler(AddressOf ValidationEventHandler)
settings.ValidationFlags = settings.ValidationFlags And XmlSchemaValidationFlags.ReportValidationWarnings
settings.ValidationType = ValidationType.Schema
Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)
' The XmlDocument validates the XML document contained
' in the XmlReader as it is loaded into the DOM.
Dim document As XmlDocument = New XmlDocument()
document.Load(reader)
' Make an invalid change to the first and last
' price elements in the XML document, and write
' the XmlSchemaInfo values assigned to the price
' element during load validation to the console.
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)
Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)
priceNode.InnerXml = "A"
Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)
lastprice.InnerXml = "B"
' Validate the XML document with the invalid changes.
' The invalid changes cause schema validation errors.
document.Validate(AddressOf ValidationEventHandler)
' Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99"
' Validate only the first book element. The last book
' element is invalid, but not included in validation.
Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
document.Validate(AddressOf ValidationEventHandler, bookNode)
Catch ex As XmlException
Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)
Catch ex As XmlSchemaValidationException
Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)
Catch ex As Exception
Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)
End Try
End Sub
Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Warning Then
Console.Write(vbCrLf & "WARNING: ")
Else
If args.Severity = XmlSeverityType.Error Then
Console.Write(vbCrLf & "ERROR: ")
End If
End If
Console.WriteLine(args.Message)
End Sub
End Class
此範例會採用 contosoBooks.xml
檔案作為輸入。
<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
<book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
<title>The Gorgias</title>
<author>
<name>Plato</name>
</author>
<price>9.99</price>
</book>
</bookstore>
此範例也會使用 contosoBooks.xsd
檔案作為輸入。
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string" />
<xs:element name="author">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string" />
<xs:element minOccurs="0" name="first-name" type="xs:string" />
<xs:element minOccurs="0" name="last-name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="price" type="xs:decimal" />
</xs:sequence>
<xs:attribute name="genre" type="xs:string" use="required" />
<xs:attribute name="publicationdate" type="xs:date" use="required" />
<xs:attribute name="ISBN" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
在驗證 XML 資料載入 DOM 時,請考慮下列事項。
在上述範例中,每當遇到無效的類型時,就會呼叫 ValidationEventHandler。 如果在驗證 XmlReader上未設定 ValidationEventHandler,當呼叫 Load 時,如果任何屬性或專案類型不符合驗證架構中指定的對應類型,則會擲回 XmlSchemaValidationException。
當 XML 檔載入至具有定義預設值之相關聯架構的 XmlDocument 物件時,XmlDocument 會將這些預設值視為出現在 XML 檔中。 這表示 IsEmptyElement 屬性總是會針對從模式預設的元素傳回
false
。 即使在 XML 文件中,它還是作為空元素寫入。
驗證 DOM 中的 XML 檔
XmlDocument 類別的 Validate 方法會根據 XmlDocument 物件的 Schemas 屬性中的架構,驗證 DOM 中載入的 XML 數據。 成功驗證之後,會套用綱要的預設值,視需要將文字值轉換成原子值,且類型資訊會與已驗證的信息項目相關聯。 因此,具類型的 XML 資料會取代先前不具類型的 XML 數據。
下列範例類似於上述「將 XML 檔載入 DOM 時驗證 XML 檔」中的範例。 在此範例中,XML 檔不會在載入 DOM 時進行驗證,而是在使用 XmlDocument 類別的 Validate 方法載入 DOM 之後進行驗證。 Validate 方法會根據 XmlDocument的 Schemas 屬性中包含的 XML 架構驗證 XML 檔。 然後對 XML 檔進行無效的修改,然後重新驗證檔,導致架構驗證錯誤。 最後,修正其中一個錯誤,然後對 XML 檔的某一部分進行部分驗證。
using System;
using System.Xml;
using System.Xml.Schema;
class XmlDocumentValidationExample
{
static void Main(string[] args)
{
try
{
// Create a new XmlDocument instance and load
// the XML document into the DOM.
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
// Add the XML schema for the XML document to the
// Schemas property of the XmlDocument.
document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
// Validate the XML document loaded into the DOM.
document.Validate(ValidationEventHandler);
// Make an invalid change to the first and last
// price elements in the XML document, and write
// the XmlSchemaInfo values assigned to the price
// element during validation to the console.
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);
Console.WriteLine($"SchemaInfo.IsDefault: {priceNode.SchemaInfo.IsDefault}");
Console.WriteLine($"SchemaInfo.IsNil: {priceNode.SchemaInfo.IsNil}");
Console.WriteLine($"SchemaInfo.SchemaElement: {priceNode.SchemaInfo.SchemaElement}");
Console.WriteLine($"SchemaInfo.SchemaType: {priceNode.SchemaInfo.SchemaType}");
Console.WriteLine($"SchemaInfo.Validity: {priceNode.SchemaInfo.Validity}");
priceNode.InnerXml = "A";
XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
XmlNode lastprice = priceNodes[priceNodes.Count - 1];
lastprice.InnerXml = "B";
// Validate the XML document with the invalid changes.
// The invalid changes cause schema validation errors.
document.Validate(ValidationEventHandler);
// Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99";
// Validate only the first book element. The last book
// element is invalid, but not included in validation.
XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
document.Validate(ValidationEventHandler, bookNode);
}
catch (XmlException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlException: {ex.Message}");
}
catch(XmlSchemaValidationException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlSchemaValidationException: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"XmlDocumentValidationExample.Exception: {ex.Message}");
}
}
static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("\nWARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("\nERROR: ");
Console.WriteLine(args.Message);
}
}
Imports System.Xml
Imports System.Xml.Schema
Class XmlDocumentValidationExample
Shared Sub Main()
Try
' Create a new XmlDocument instance and load
' the XML document into the DOM.
Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml")
' Add the XML schema for the XML document to the
' Schemas property of the XmlDocument.
document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
' Validate the XML document loaded into the DOM.
document.Validate(AddressOf ValidationEventHandler)
' Make an invalid change to the first and last
' price elements in the XML document, and write
' the XmlSchemaInfo values assigned to the price
' element during validation to the console.
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)
Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)
priceNode.InnerXml = "A"
Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)
lastprice.InnerXml = "B"
' Validate the XML document with the invalid changes.
' The invalid changes cause schema validation errors.
document.Validate(AddressOf ValidationEventHandler)
' Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99"
' Validate only the first book element. The last book
' element is invalid, but not included in validation.
Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
document.Validate(AddressOf ValidationEventHandler, bookNode)
Catch ex As XmlException
Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)
Catch ex As XmlSchemaValidationException
Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)
Catch ex As Exception
Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)
End Try
End Sub
Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Warning Then
Console.Write(vbCrLf & "WARNING: ")
Else
If args.Severity = XmlSeverityType.Error Then
Console.Write(vbCrLf & "ERROR: ")
End If
End If
Console.WriteLine(args.Message)
End Sub
End Class
此範例會採用輸入 contosoBooks.xml
和 contosoBooks.xsd
檔案,如上面「載入 DOM 時驗證 XML 檔」中所述。
處理驗證錯誤和警告
驗證載入 DOM 中的 XML 資料時,會報告 XML 架構驗證錯誤。 當 XML 資料載入時,或驗證先前未驗證的 XML 檔時,您會收到有關驗證 XML 數據時發現之所有架構驗證錯誤的通知。
驗證錯誤是由 ValidationEventHandler處理。 如果將 ValidationEventHandler 指派給 XmlReaderSettings 實例,或傳遞至 XmlDocument 類別的 Validate 方法,則 ValidationEventHandler 會處理架構驗證錯誤;否則,遇到架構驗證錯誤時,就會引發 XmlSchemaValidationException。
備註
除非您的 ValidationEventHandler 引發例外狀況來停止進程,否則 XML 數據會載入 DOM 中,除非發生架構驗證錯誤。
除非將 ReportValidationWarnings 旗標指定給 XmlReaderSettings 對象,否則不會報告架構驗證警告。
如需說明