该 XPathNavigator 类提供一组用于修改 XML 文档中的节点和值的方法。 若要使用这些方法, XPathNavigator 对象必须可编辑,也就是说,其 CanEdit 属性必须为 true
。
XPathNavigator 可以编辑 XML 文档的对象由 CreateNavigator 类的方法 XmlDocument 创建。 XPathNavigator类XPathDocument创建的对象是只读的,任何尝试使用由XPathNavigator创建的XPathDocument对象的编辑方法都会导致NotSupportedException。
有关创建可 XPathNavigator 编辑对象的详细信息,请参阅 使用 XPathDocument 和 XmlDocument 读取 XML 数据。
修改节点
更改节点值的简单方法是使用SetValue类的SetTypedValue和XPathNavigator方法。
下表列出了这些方法对不同节点类型的影响。
XPathNodeType | 数据已更改 |
---|---|
Root | 不支持。 |
Element | 元素的内容。 |
Attribute | 特性的值。 |
Text | 文本内容。 |
ProcessingInstruction | 内容(排除目标对象)。 |
Comment | 注释的内容。 |
Namespace | 。 |
该 XPathNavigator 类还提供一组用于插入和删除节点的方法。 有关从 XML 文档中插入和删除节点的详细信息,请参阅 使用 XPathNavigator 插入 XML 数据 ,以及 使用 XPathNavigator 删除 XML 数据 的主题。
修改非类型化值
该方法 SetValue 只是将未经过类型化的 string
值作为参数传递,并作为 XPathNavigator 对象当前所在节点的值插入。 当没有指定任何类型,或者没有验证新值在有架构信息的情况下是否符合节点类型时,该值被插入。
在以下示例中,SetValue 方法用于更新 price
文件中的所有 contosoBooks.xml
元素。
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();
XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
foreach (XPathNavigator nav in navigator.Select("//bk:price", manager))
{
if (nav.Value == "11.99")
{
nav.SetValue("12.99");
}
}
Console.WriteLine(navigator.OuterXml);
Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(navigator.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
For Each nav As XPathNavigator In navigator.Select("//bk:price", manager)
If nav.Value = "11.99" Then
nav.SetValue("12.99")
End If
Next
Console.WriteLine(navigator.OuterXml)
该示例将 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>
修改已定义的类型值
当节点的类型为 W3C XML 架构简单类型时,该方法 SetTypedValue 插入的新值将针对简单类型的分面进行检查,然后再设置该值。 如果新值根据节点的类型无效(例如,在类型为-1
元素上设置值xs:positiveInteger
),则会导致异常。
以下示例尝试将price
文件中第一个book
元素的contosoBooks.xml
元素的值更改为DateTime的值。 由于price
文件中元素xs:decimal
的XML Schema类型被定义为contosoBooks.xsd
,因此会导致异常。
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
settings.ValidationType = ValidationType.Schema
Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)
Dim document As XmlDocument = New XmlDocument()
document.Load(reader)
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", "http://www.contoso.com/books")
navigator.MoveToChild("book", "http://www.contoso.com/books")
navigator.MoveToChild("price", "http://www.contoso.com/books")
navigator.SetTypedValue(DateTime.Now)
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");
navigator.MoveToChild("price", "http://www.contoso.com/books");
navigator.SetTypedValue(DateTime.Now);
该示例将 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 数据的效果
该 XPathNavigator 类使用 W3C XML 架构作为描述强类型 XML 的基础。 元素和属性可以根据 W3C XML 架构文档的验证使用类型信息进行批注。 可以包含其他元素或属性的元素称为复杂类型,而只能包含文本内容的元素称为简单类型。
注释
属性只能有简单类型。
如果元素或属性符合特定于其类型定义的所有规则,则可以将其视为架构有效。 具有简单类型的 xs:int
元素必须包含 -2147483648 和2147483647之间的数值才能架构有效。 对于复杂类型,元素的架构有效性取决于其子元素和属性的架构有效性。 因此,如果元素对其复杂类型定义有效,则其所有子元素和属性都对其类型定义有效。 同样,如果某个元素的任何一个子元素或属性对其类型定义无效,或者具有未知的有效性,该元素也被视为无效或有效性未知。
鉴于元素的有效性取决于其子元素和属性的有效性,对任一元素的修改会导致在元素以前有效时更改元素的有效性。 具体而言,如果插入、更新或删除元素的子元素或属性,则该元素的有效性将变为未知。 元素的Validity属性中将SchemaInfo属性设置为NotKnown进行表示。 此外,由于元素的父元素(以及它的父元素,依此类推)的有效性也变得未知,因此这种效果在 XML 文档中以递归的方式向上级联。
有关架构验证和 XPathNavigator 类的详细信息,请参阅 使用 XPathNavigator 的架构验证。
修改属性
SetValue和SetTypedValue方法可用于修改非类型化和类型化属性节点以及“修改节点”部分中列出的其他节点类型。
以下示例更改genre
文件中第一个book
元素的books.xml
属性的值。
Dim document As XmlDocument = New XmlDocument()
document.Load("books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", String.Empty)
navigator.MoveToChild("book", String.Empty)
navigator.MoveToAttribute("genre", String.Empty)
navigator.SetValue("non-fiction")
navigator.MoveToRoot()
Console.WriteLine(navigator.OuterXml)
XmlDocument document = new XmlDocument();
document.Load("books.xml");
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToChild("bookstore", String.Empty);
navigator.MoveToChild("book", String.Empty);
navigator.MoveToAttribute("genre", String.Empty);
navigator.SetValue("non-fiction");
navigator.MoveToRoot();
Console.WriteLine(navigator.OuterXml);
有关SetValue和SetTypedValue方法的详细信息,请参阅“修改非类型化值”和“修改类型化值”部分。
InnerXml 和 OuterXml 属性
InnerXml类的OuterXml和XPathNavigator属性更改XPathNavigator对象当前定位节点的 XML 标记。
该 InnerXml 属性将给定 XML XPathNavigator 的解析内容应用于该对象当前定位的子节点,从而更改其 XML 标记。 同样,属性 OuterXml 更改对象当前位于的子节点 XPathNavigator 的 XML 标记以及当前节点本身。
以下示例使用OuterXml该属性修改元素的值price
,并在文件中的第一个discount
元素book
上插入一个新contosoBooks.xml
属性。
Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml");
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", "http://www.contoso.com/books")
navigator.MoveToChild("book", "http://www.contoso.com/books")
navigator.MoveToChild("price", "http://www.contoso.com/books")
navigator.OuterXml = "<price discount=\"0\">10.99</price>"
navigator.MoveToRoot()
Console.WriteLine(navigator.OuterXml)
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");
navigator.MoveToChild("price", "http://www.contoso.com/books");
navigator.OuterXml = "<price discount=\"0\">10.99</price>";
navigator.MoveToRoot();
Console.WriteLine(navigator.OuterXml);
该示例将 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>
修改命名空间节点
在文档对象模型(DOM)中,命名空间声明被视为可以插入、更新和删除的常规属性。 该 XPathNavigator 类不允许在命名空间节点上执行此类作,因为更改命名空间节点的值可以更改命名空间节点范围内元素和属性的标识,如以下示例所示。
<root xmlns="http://www.contoso.com">
<child />
</root>
如果上述 XML 示例按以下方式更改,则会有效地重命名文档中的每一个元素,因为每个元素的命名空间 URI 的值已更改。
<root xmlns="urn:contoso.com">
<child />
</root>
在插入范围内不与命名空间声明冲突的命名空间节点可以由 XPathNavigator 类插入。 在这种情况下,命名空间声明没有在 XML 文档的较低层次范围中声明,因此不会导致重命名,如以下示例所示。
<root xmlns:a="http://www.contoso.com">
<parent>
<a:child />
</parent>
</root>
如果上述 XML 示例按以下方式更改,命名空间声明将正确传播到其他命名空间声明范围下面的 XML 文档中。
<root xmlns:a="http://www.contoso.com">
<parent a:parent-id="1234" xmlns:a="http://www.contoso.com/parent-id">
<a:child xmlns:a="http://www.contoso.com/" />
</parent>
</root>
在上面的 XML 示例中,属性 a:parent-id
被插入到命名空间 parent
中的 http://www.contoso.com/parent-id
元素上。 该方法 CreateAttribute 用于在 parent
元素定位时插入属性。 命名空间 http://www.contoso.com
声明由 XPathNavigator 类自动插入,以保留 XML 文档的其余部分的一致性。
修改实体引用节点
对象中的 XmlDocument 实体引用节点是只读的,不能使用 XPathNavigator 或 XmlNode 类进行编辑。 任何修改实体引用节点的尝试都会导致 InvalidOperationException.
修改 xsi:nil 节点
W3C XML 架构建议引入了元素不可删除的概念。 当元素为 nillable 时,元素可能没有内容,并且仍然有效。 元素为 nillable 的概念类似于对象 null
的概念。 主要区别是 null
不能以任何方式访问对象,而 xsi:nil
元素仍具有属性(可以访问的属性),但没有内容(子元素或文本)。 在一个 XML 文档中,元素上具有xsi:nil
属性且取值为true
的存在,用于指示该元素没有内容。
如果对象XPathNavigator用于向具有值xsi:nil
的属性的有效元素true
添加内容,则其xsi:nil
特性的值设置为 false
。
注释
如果删除了属性xsi:nil
设置为false
的元素的内容,则属性的值不会更改为true
。
保存 XML 文档
在本主题中所述的编辑方法的结果是使用XmlDocument类的方法来保存对XmlDocument对象所做的更改。 有关保存对 XmlDocument 对象所做的更改的详细信息,请参阅 “保存和写入文档”。