Language

XPathNavigator を使用して XML データを変更する

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

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

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

ノードの変更

ノードの値を変更する簡単な手法は、SetValue クラスのSetTypedValueメソッドと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 = 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 を持つ要素は、スキーマとして有効であるために、-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 プロパティは、XPathNavigator オブジェクトが現在配置されている子ノードの XML マークアップを、指定された XML stringの解析された内容と共に変更します。 同様に、 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) では、名前空間宣言は、挿入、更新、および削除できる通常の属性であるかのように扱われます。 次の例に示すように、名前空間ノードの値を変更すると、名前空間ノードのスコープ内の要素と属性の ID が変更される可能性があるため、 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名前空間宣言は、XML ドキュメントの残りの部分の一貫性を維持するために、XPathNavigator クラスによって自動的に挿入されます。

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

XmlDocument オブジェクト内のエンティティ参照ノードは読み取り専用であり、XPathNavigatorクラスまたはXmlNode クラスを使用して編集することはできません。 エンティティ参照ノードを変更しようとすると、 InvalidOperationExceptionが発生します。

xsi:nil ノードの変更

W3C XML スキーマの推奨事項では、要素が nillable であるという概念が導入されています。 要素が nillable の場合、要素にコンテンツがなく、有効なままである可能性があります。 要素が「null許容型」であるという概念は、オブジェクトがnullであるという概念に似ています。 主な違いは、 null オブジェクトに何らかの方法でアクセスできないのに対し、 xsi:nil 要素には、アクセスできるがコンテンツ (子要素やテキスト) を持たない属性などのプロパティが残っている点です。 XML ドキュメント内の要素にxsi:nil値を持つtrue属性の存在は、要素にコンテンツがないことを示すために使用されます。

XPathNavigator オブジェクトを使用して、xsi:nilの値を持つtrue属性を持つ有効な要素にコンテンツを追加する場合、そのxsi:nil属性の値はfalseに設定されます。

注

xsi:nil属性が false に設定されている要素の内容が削除された場合、属性の値は true に変更されません。

XML ドキュメントの保存

このトピックで説明する編集メソッドの結果として XmlDocument オブジェクトに加えられた変更の保存は、 XmlDocument クラスのメソッドを使用して実行されます。 XmlDocument オブジェクトに加えられた変更の保存の詳細については、「ドキュメントの保存と書き込み」を参照してください。

こちらも参照ください