共用方式為


使用 XPathNavigator 修改 XML 數據

類別 XPathNavigator 提供一組方法來修改 XML 檔案中的節點和值。 若要使用這些方法, XPathNavigator 對象必須可編輯,也就是說,其 CanEdit 屬性必須是 true

XPathNavigator 可以編輯 XML 檔的物件是由 CreateNavigator 類別的 XmlDocument 方法所建立。 XPathNavigator 類別建立的物件是唯讀的,而且任何嘗試使用 XPathDocument 物件所建立的 XPathNavigator 物件的編輯方法都會導致 XPathDocument

如需建立可 XPathNavigator 編輯對象的詳細資訊,請參閱 使用 XPathDocument 和 XmlDocument 讀取 XML 數據

修改節點

變更節點值的簡單技巧是使用 SetValue 類別的 SetTypedValueXPathNavigator 方法。

下表列出這些方法對不同節點類型的影響。

XPathNodeType 數據已變更
Root 不支援。
Element 元素的內容。
Attribute 屬性的值。
Text 文字內容。
ProcessingInstruction 內容,不包括目標。
Comment 批注的內容。
Namespace 不支援。

備註

不支援編輯 Namespace 節點或 Root 節點。

類別 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 的新值會在設定值之前,針對簡單類型的 Facet 進行檢查。 如果新值根據節點的類型無效(例如,在類型為-1的項目上設定 值xs:positiveInteger),則會產生例外狀況。

下列範例會嘗試將檔案中第一個price元素的 book值變更為 contosoBooks.xml值。 由於 price 檔案中將 xs:decimal 元素的 XML 架構類型定義為 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 的架構驗證

更改屬性

SetValueSetTypedValue 方法可用來修改不具類型的屬性節點,以及「修改節點」區段中所列的其他節點類型。

下列範例會變更檔案中genre第一個項目bookbooks.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);

如需 SetValueSetTypedValue 方法的詳細資訊,請參閱「修改未定型值」和「修改定型值」章節。

InnerXml 和 OuterXml 屬性

類別InnerXmlOuterXmlXPathNavigator 屬性會變更物件目前所在的節點 XPathNavigator XML 標記。

InnerXml 屬性會根據指定的 XML XPathNavigator 剖析內容,變更物件 string 目前所在子節點的 XML 標記。 同樣地,OuterXml 屬性會更改目前物件所在的子節點和目前節點本身的 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實體參考節點是唯讀的,無法使用XPathNavigatorXmlNode類別進行編輯。 任何修改實體參考節點的嘗試都會導致 InvalidOperationException

修改 xsi:nil 節點

W3C XML 架構建議引進了元素為 nillable 的概念。 當元素為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 變更的詳細資訊,請參閱 儲存和寫入檔

另請參閱