使用 XPathNavigator 访问强类型 XML 数据
更新:November 2007
作为 XPath 2.0 数据模型的实例,XPathNavigator 类可以包含映射到公共语言运行库 (CLR) 类型的强类型数据。根据 XPath 2.0 数据模型,只有元素和属性可以包含强类型数据。XPathNavigator 类提供将 XPathDocument 或 XmlDocument 对象中的数据作为强类型数据访问的机制,以及将一种数据类型转换为另一种数据类型的机制。
通过 XPathNavigator 公开的类型信息
XML 1.0 数据在技术角度没有类型,除非使用 DTD、XML 架构定义语言 (XSD) 架构或其他机制进行处理。有许多类别的类型信息可以与 XML 元素或属性关联。
简单 CLR 类型:任何 XML 架构语言均不直接支持公共语言运行库 (CLR) 类型。因为能够以最适合的 CLR 类型查看简单元素和属性内容非常有用,所以,在缺少架构信息以及任何添加的架构信息(可能会将此内容优化为更适合的类型)时,可以将所有简单内容类型化为 String。可以使用 ValueType 属性找到简单元素和属性内容最匹配的 CLR 类型。有关从架构内置类型映射到 CLR 类型的更多信息,请参见 System.Xml 类中的类型支持。
简单 (CLR) 类型的列表:具有简单内容的元素或属性可以包含通过空格分隔的值列表。XML 架构将这些值指定为“列表类型”。在缺少 XML 架构时,此类简单内容将作为单个文本节点对待。在 XML 架构可用时,此简单内容可以作为一系列原子值公开,每个值都具有一种映射到 CLR 对象集合的简单类型。有关从架构内置类型映射到 CLR 类型的更多信息,请参见 System.Xml 类中的类型支持。
类型化值:已经过架构验证的属性或具有简单类型的元素具有类型化的值。此值是基元类型,例如数字、字符串或日期类型。XSD 中的所有内置简单类型均可以映射到 CLR 类型,通过 CLR 类型可以以更适合的类型(而不只是以 String)访问节点的值。具有属性或元素子级的元素被认为是复杂类型。包含简单内容(只有文本节点作为子级)的复杂类型的类型化值与其内容的简单类型的类型化值相同。包含复杂内容(一个或多个子元素)的复杂类型的类型化值是串联以 String 形式返回的所有子文本节点的字符串值。有关从架构内置类型映射到 CLR 类型的更多信息,请参见 System.Xml 类中的类型支持。
架构语言特定的类型名称:在大多数情况下,作为应用外部架构副产品设置的 CLR 类型用于提供对节点值的访问。但是,有时可能需要检查与应用于 XML 文档的特定架构相关联的类型。例如,可能希望搜索 XML 文档,根据附加的架构提取确定包含“PurchaseOrder”类型内容的所有元素。此类信息只能设置为架构验证的结果,此信息通过 XPathNavigator 类的 XmlType 和 SchemaInfo 属性访问。有关更多信息,请参见下面的“后架构验证信息集 (PSVI)”一节。
架构语言特定的类型反射:在其他情况下,可能需要获取应用于 XML 文档的架构特定类型的更多详细信息。例如,在读取 XML 文件时,可能需要为 XML 文档中的每个有效节点提取 maxOccurs 属性,以便执行某项自定义计算。因为此信息仅通过架构验证设置,所以,通过 XPathNavigator 类的 SchemaInfo 属性访问。有关更多信息,请参见下面的“后架构验证信息集 (PSVI)”一节。
XPathNavigator 类型化访问器
下表显示 XPathNavigator 类中可以用于访问节点的类型信息的各种属性和方法。
属性 |
说明 |
---|---|
此属性包含节点(如果有效)的 XML 架构类型信息。 |
|
此属性包含在验证之后添加的节点的后架构验证信息集。其中包括 XML 架构类型信息以及有效性信息。 |
|
节点的类型化值的 CLR 类型。 |
|
作为类型与节点的 XML 架构类型最匹配的一个或多个 CLR 值的节点内容。 |
|
当前节点的 String 值根据 xs:boolean 的 XPath 2.0 强制转换规则强制转换为 Boolean 值。 |
|
当前节点的 String 值根据 xs:datetime 的 XPath 2.0 强制转换规则强制转换为 DateTime 值。 |
|
当前节点的 String 值根据 xsd:double 的 XPath 2.0 强制转换规则强制转换为 Double 值。 |
|
当前节点的 String 值根据 xs:integer 的 XPath 2.0 强制转换规则强制转换为 Int32 值。 |
|
当前节点的 String 值根据 xs:integer 的 XPath 2.0 强制转换规则强制转换为 Int64 值。 |
|
节点内容根据 XPath 2.0 强制转换规则强制转换为目标类型。 |
有关从架构内置类型映射到 CLR 类型的更多信息,请参见 System.Xml 类中的类型支持。
后架构验证信息集 (PSVI)
XML 架构处理器使用 XML 信息集作为输入,并将其转换为后架构验证信息集 (PSVI)。PSVI 是原始输入 XML 信息集,包含添加的新信息项以及在现有信息项中添加的新属性。在 PSVI 的 XML 信息集中添加了三种广义信息类,通过 XPathNavigator 公开。
验证结果:有关元素或属性是否已成功验证的信息。此信息通过 XPathNavigator 类的 Validity 属性的 SchemaInfo 属性公开。
默认的信息:有关元素或属性的值是否已通过架构中指定的默认值获取的信息。此信息通过 XPathNavigator 类的 IsDefault 属性的 SchemaInfo 属性公开。
类型批注:对架构组件的参考,可能是类型定义或元素和属性的声明。XPathNavigator 的 XmlType 属性包含节点(如果有效)的特定类型信息。如果节点的有效性未知,例如节点在验证后进行了编辑,XmlType 属性将设置为 null,但是类型信息仍可以通过 XPathNavigator 类的 SchemaInfo 属性的各种属性访问。
以下示例说明如何使用通过 XPathNavigator 公开的后架构验证信息集中的信息。
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.Schemas.Add("https://www.contoso.com/books", "books.xsd")
settings.ValidationType = ValidationType.Schema
Dim reader As XmlReader = XmlReader.Create("books.xml", settings)
Dim document As XmlDocument = New XmlDocument()
document.Load(reader)
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("books", "https://www.contoso.com/books")
navigator.MoveToChild("book", "https://www.contoso.com/books")
navigator.MoveToChild("published", "https://www.contoso.com/books")
Console.WriteLine(navigator.SchemaInfo.SchemaType.Name)
Console.WriteLine(navigator.SchemaInfo.Validity)
Console.WriteLine(navigator.SchemaInfo.SchemaElement.MinOccurs)
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("https://www.contoso.com/books", "books.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("books.xml", settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToChild("books", "https://www.contoso.com/books");
navigator.MoveToChild("book", "https://www.contoso.com/books");
navigator.MoveToChild("published", "https://www.contoso.com/books");
Console.WriteLine(navigator.SchemaInfo.SchemaType.Name);
Console.WriteLine(navigator.SchemaInfo.Validity);
Console.WriteLine(navigator.SchemaInfo.SchemaElement.MinOccurs);
该示例使用 books.xml 文件作为输入。
<books xmlns="https://www.contoso.com/books">
<book>
<title>Title</title>
<price>10.00</price>
<published>2003-12-31</published>
</book>
</books>
该示例还使用 books.xsd 架构作为输入。
<xs:schema xmlns="https://www.contoso.com/books"
attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="https://www.contoso.com/books"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="publishedType">
<xs:restriction base="xs:date">
<xs:minInclusive value="2003-01-01" />
<xs:maxInclusive value="2003-12-31" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="bookType">
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="price" type="xs:decimal"/>
<xs:element name="published" type="publishedType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="booksType">
<xs:sequence>
<xs:element name="book" type="bookType" />
</xs:sequence>
</xs:complexType>
<xs:element name="books" type="booksType" />
</xs:schema>
使用 ValueAs 属性获取类型化值
节点的类型化值可以通过访问 XPathNavigator 的 TypedValue 属性进行检索。在某些情况下,可能需要将节点的类型化值转换为其他类型。常见的示例是从 XML 节点获取数值。例如,考虑以下未经过验证和非类型化的 XML 文档。
<books>
<book>
<title>Title</title>
<price>10.00</price>
<published>2003-12-31</published>
</book>
</books>
如果 XPathNavigator 位于 price 元素上,XmlType 属性将为 null,ValueType 属性将为 String,TypedValue 属性将为字符串 10.00。
但是,仍可以使用 ValueAs、ValueAsDouble、ValueAsInt 或 ValueAsLong 方法和属性以数值形式提取该值。以下示例说明如何使用 ValueAs 方法执行此类强制转换。
Dim document As New XmlDocument()
document.Load("books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("books", "")
navigator.MoveToChild("book", "")
navigator.MoveToChild("price", "")
Dim price = navigator.ValueAs(GetType(Decimal))
Dim discount As Decimal = 0.2
Console.WriteLine("The price of the book has been dropped 20% from {0:C} to {1:C}", navigator.Value, (price - price * discount))
XmlDocument document = new XmlDocument();
document.Load("books.xml");
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToChild("books", "");
navigator.MoveToChild("book", "");
navigator.MoveToChild("price", "");
Decimal price = (decimal)navigator.ValueAs(typeof(decimal));
Console.WriteLine("The price of the book has been dropped 20% from {0:C} to {1:C}", navigator.Value, (price - price * (decimal)0.20));
有关从架构内置类型映射到 CLR 类型的更多信息,请参见 System.Xml 类中的类型支持。
请参见
概念
使用 XPathNavigator 的属性和命名空间节点定位