XpathNavigator による XML データの変更

XPathNavigator クラスは、XML ドキュメント内のノードを変更するためのメソッドのセットを提供します。 これらのメソッドを使用するには、XPathNavigator オブジェクトが編集可能である必要があります。つまり、その CanEdit プロパティを true にする必要があります。

XML ドキュメントを編集できる XPathNavigator オブジェクトは、CreateNavigator クラスの XmlDocument メソッドによって作成されます。 XPathNavigator クラスによって作成される XPathDocument オブジェクトは読み取り専用で、XPathNavigator オブジェクトによって作成される XPathDocument オブジェクトの編集メソッドを使用しようとすると、NotSupportedException が発生します。

編集可能な XPathNavigator オブジェクトの作成方法については、「XPathDocument および XmlDocument を使用した XML データの読み取り」を参照してください。

ノードの変更

ノードの値を簡単に変更するには、SetValueSetTypedValue クラスの XPathNavigator メソッドを使用します。

次の表は、異なるノード型に対するこれらメソッドの効果の一覧です。

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 = gcnew XmlDocument();
document->Load("contosoBooks.xml");
XPathNavigator^ navigator = document->CreateNavigator();

XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(navigator->NameTable);
manager->AddNamespace("bk", "http://www.contoso.com/books");

for each (XPathNavigator^ nav in navigator->Select("//bk:price", manager))
{
    if(nav->Value == "11.99")
    {
        nav->SetValue("12.99");
    }
}

Console::WriteLine(navigator->OuterXml);
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 要素の XML スキーマ型は、xs:decimal ファイル内で 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 クラスは、厳密に型指定された XML の記述の基本に W3C XML スキーマを使用します。 要素および属性には、W3C XML スキーマ ドキュメントに対する検証に基づいて、型情報を使用して注釈を付けることができます。 他の要素または属性を含めることができる要素は、複合型と呼ばれ、テキストの内容だけを含めることのできる要素は単純型と呼ばれます。

注意

属性には単純型しかありません。

要素または属性は、その型定義に固有のすべての規則に準拠している場合、スキーマ有効と見なされます。 単純型の要素 xs:int がスキーマ有効であるためには、-2,147,483,648 ~ 2,147,483,647 の数値を含む必要があります。 複合型の場合、要素のスキーマ有効性は、その子の要素および属性のスキーマ有効性に依存します。 したがって、要素が複合型定義に対して有効な場合、その子の要素および属性はすべて、それらの型定義に対して有効です。 同様に、要素の子の要素または属性のうち 1 つでもその型定義に対して無効か有効性が不明な場合、その要素も無効か有効性が不明になります。

要素の有効性がその子の要素および属性の有効性に依存することを考えると、要素が以前有効だった場合、どちらを変更しても要素の有効性が変わる結果になります。 具体的には、要素の子要素または属性が挿入、更新または削除されると、その要素の有効性は不明になります。 これは、要素の 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 の解析済みの内容を使用して string オブジェクトの現在位置にある子ノードの 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 クラスでは、名前空間ノードに対してそのような操作は許可されません。これは、次の例で説明されているように、名前空間ノードの値を変更すると、名前空間ノードのスコープ内の要素および属性の ID が変更される可能性があるためです。

<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-idparent 名前空間名の http://www.contoso.com/parent-id 要素に挿入されます。 CreateAttribute メソッドは、parent 要素上に位置しているときの属性の挿入に使用されます。 XML ドキュメントの残りの部分の一貫性を保持するために、http://www.contoso.com 名前空間宣言が XPathNavigator クラスによって自動的に挿入されます。

エンティティ参照ノードの変更

XmlDocument オブジェクト内のエンティティ参照ノードは、読み取り専用で、XPathNavigator または XmlNode クラスのどちらを使用しても編集できません。 エンティティ参照ノードを変更しようとすると、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 オブジェクトに対する変更の保存に関する詳細については、「ドキュメントの保存と書き込み」を参照してください。

関連項目