Freigeben über


Ändern von XML-Daten mit "XPathNavigator"

Die XPathNavigator-Klasse stellt eine Gruppe von Methoden bereit, die zum Ändern von Knoten und Werten eines XML-Dokuments verwendet werden. Diese Methoden können nur dann verwendet werden, wenn das XPathNavigator-Objekt bearbeitet werden kann, d. h. seine CanEdit-Eigenschaft muss true sein.

XPathNavigator-Objekte, die ein XML-Dokument bearbeiten können, werden von der CreateNavigator-Methode der XmlDocument-Klasse erstellt. XPathNavigator-Objekte, die von der XPathDocument-Klasse erstellt werden, sind schreibgeschützt. Der Versuch, die Bearbeitungsmethoden eines XPathNavigator-Objekts anzuwenden, das von einem XPathDocument-Objekt erstellt wurde, führt zu einer NotSupportedException.

Weitere Informationen zum Erstellen bearbeitbarer XPathNavigator-Objekte finden Sie unter Lesen von XML-Daten mithilfe von XPathDocument und XmlDocument.

Ändern von Knoten

Ein einfaches Verfahren zum Ändern des Werts eines Knotens ist die Verwendung der SetValue-Methode und der SetTypedValue-Methode der XPathNavigator-Klasse.

In der folgenden Tabelle ist die Wirkung dieser Methoden für verschiedene Knotentypen aufgeführt.

XPathNodeType Geänderte Daten
Root Wird nicht unterstützt.
Element Der Inhalt des Elements.
Attribute Der Wert des Attributs.
Text Der Textinhalt.
ProcessingInstruction Der Inhalt mit Ausnahme des Ziels.
Comment Der Inhalt des Kommentars.
Namespace Nicht unterstützt.

Hinweis

Das Bearbeiten von Namespace-Knoten oder des Root-Knotens wird nicht unterstützt.

Die XPathNavigator-Klasse stellt ebenfalls eine Gruppe von Methoden zum Einfügen und Entfernen von Knoten bereit. Weitere Informationen zum Einfügen und Entfernen von Knoten aus einem XML-Dokument finden Sie in den Themen Einfügen von XML-Daten mit XPathNavigator und Entfernen von XML-Daten mit XPathNavigator.

Ändern von nicht typisierten Werten

Die SetValue-Methode fügt einfach den als Parameter übergebenen nicht typisierten string-Wert als Wert des Knotens ein, auf dem das XPathNavigator-Objekt gerade positioniert ist. Der Wert wird ohne Typ bzw. (falls Schemainformationen verfügbar sind) ohne Prüfung der Gültigkeit des neuen Werts bezüglich des Knotentyps eingefügt.

Im folgenden Beispiel werden alle SetValue-Elemente in der Datei price mit der contosoBooks.xml-Methode aktualisiert.

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)

In diesem Beispiel wird die Datei contosoBooks.xml als Eingabe verwendet.

<?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>

Ändern von typisierten Werten

Wenn der Typ ein einfacher W3C-XML-Schematyp ist, wird der neue mit der SetTypedValue-Methode eingefügte Wert anhand aller Facets des einfachen Typs überprüft, bevor er festgelegt wird. Wenn der neue Wert bezüglich des Knotentyps nicht gültig ist (z. B. der Wert -1 für ein Element vom Typ xs:positiveInteger), wird eine Ausnahme ausgelöst.

Im folgenden Beispiel wird versucht, den Wert des price-Elements des ersten book-Elements der Datei contosoBooks.xml in einen DateTime-Wert zu ändern. Da der XML-Schematyp des price-Elements in den xs:decimal-Dateien als contosoBooks.xsd definiert ist, führt dies zu einer Ausnahme.

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);  

In diesem Beispiel wird die Datei contosoBooks.xml als Eingabe verwendet.

<?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>

In diesem Beispiel wird auch contosoBooks.xsd als Eingabe verwendet.

<?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>

Die Auswirkungen der Änderung von stark typisierten XML-Daten

Die XPathNavigator-Klasse verwendet das W3C-XML-Schema als Grundlage für die Beschreibung von stark typisiertem XML. Zu Elementen und Attributen können auf der Grundlage der Validierung mit einem W3C-XML-Schemadokument Typinformationen angemerkt werden. Elemente, die andere Elemente oder Attribute enthalten können, werden als komplexe Typen bezeichnet. Elemente, die nur Inhalt in Form von Text enthalten können, werden als einfache Typen bezeichnet.

Hinweis

Attribute können nur einfache Typen haben.

Ein Element oder Attribut kann als Schema-gültig betrachtet werden, wenn es alle spezifischen Regeln der Typdefinition genügt. Ein Element mit dem einfachen Typ xs:int ist nur dann gültig, wenn es einen numerischen Wert zwischen -2147483648 und 2147483647 enthält. Bei komplexen Typen hängt die Schema-Gültigkeit der Elemente von der Schema-Gültigkeit der untergeordneten Elemente und Attribute ab. Wenn ein Element bezüglich einer komplexen Typdefinition gültig ist, dann sind auch alle untergeordneten Elemente und Attribute bezüglich deren Definitionen gültig. Wenn auch nur ein einziges untergeordnetes Element oder Attribut bezüglich seiner Typdefinition ungültig ist oder wenn die Gültigkeit nicht bekannt ist, ist das Element entweder ungültig, oder die Gültigkeit ist unbekannt.

Da die Gültigkeit eines Elements von der Gültigkeit seiner untergeordneten Elemente und Attribute abhängt, führen Änderungen dazu, dass sich die Gültigkeit des Elements ändert, wenn es vorher gültig war. Insbesondere wird die Gültigkeit eines Elements unbekannt, wenn untergeordnete Elemente oder Attribute des Elements eingefügt, aktualisiert oder gelöscht werden. Dies wird durch Festlegen der Validity-Eigenschaft der SchemaInfo-Eigenschaft des Elements auf NotKnown dargestellt. Darüber hinaus setzt sich diese Auswirkung rekursiv aufwärts innerhalb des XML-Dokuments fort, da die Gültigkeit des übergeordneten Elements (und des diesem Element übergeordneten Elements usw.) eines Elements ebenfalls unbekannt wird.

Weitere Informationen über Schemavalidierung und die XPathNavigator-Klasse finden Sie unter Schemaüberprüfung mit XPathNavigator.

Ändern von Attributen

Mit der SetValue-Methode und der SetTypedValue-Methode können nicht typisierte und typisierte Attributknoten sowie die anderen im Abschnitt "Ändern von Knoten" aufgeführten Knotentypen geändert werden.

Im fogenden Beispiel wird der Wert des genre-Attributs des ersten book-Elements der Datei books.xml geändert.

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);  

Weitere Informationen über die SetValue-Methode und die SetTypedValue-Methode finden Sie in den Abschnitten "Ändern von nicht typisierten Werten" und "Ändern von typisierten Werten".

Die Eigenschaften "InnerXml" und "OuterXml"

Die InnerXml-Eigenschaft und die OuterXml-Eigenschaft der XPathNavigator-Klasse ändern das XML-Markup der Knoten, auf denen derzeit ein XPathNavigator-Objekt positioniert ist.

Die InnerXml-Eigenschaft ändert das XML-Markup der untergeordneten Knoten, auf denen derzeit ein XPathNavigator-Objekt positioniert ist, mit den analysierten Inhalten des angegebenen XML-string. Ebenso ändert die OuterXml-Eigenschaft das XML-Markup der untergeordneten Knoten, auf denen derzeit ein XPathNavigator-Objekt positioniert ist, sowie den aktuellen Knoten selbst.

Im folgenden Beispiel wird mit der OuterXml-Eigenschaft der Wert des price-Elements geändert und in das erste discount-Element der Datei book ein neues contosoBooks.xml-Attribut eingefügt.

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);  

In diesem Beispiel wird die Datei contosoBooks.xml als Eingabe verwendet.

<?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>

Ändern von Namespaceknoten

Im DOM (Document Object Model) werden Namespacedeklarationen wie normale Attribute behandelt, die eingefügt, aktualisiert und gelöscht werden können. Die XPathNavigator-Klasse lässt derartige Operationen auf Namespaceknoten nicht zu, da eine Änderung des Werts eines Namespaceknotens die Identität der Elemente innerhalb des Gültigkeitsbereichs des Namespaceknotens ändern kann. Dies wird im folgenden Beispiel veranschaulicht.

<root xmlns="http://www.contoso.com">  
    <child />  
</root>  

Wenn das obige XML-Beispiel wie folgt geändert wird, wird dadurch jedes Element des Dokuments umbenannt, da sich der Wert des Namespace-URI aller Elemente ändert.

<root xmlns="urn:contoso.com">  
    <child />  
</root>  

Die XPathNavigator-Klasse lässt das Einfügen von Namespaceknoten zu, wenn kein Konflikt innerhalb des Gültigkeitsbereichs, in den sie eingefügt werden, besteht. In diesem Fall befinden sich die Namespacedeklarationen nicht in niedrigeren Gültigkeitsbereichen des XML-Dokuments und führen daher nicht zu einer Umbenennung. Dies wird im folgenden Beispiel veranschaulicht.

<root xmlns:a="http://www.contoso.com">  
    <parent>  
        <a:child />  
    </parent>  
</root>  

Wenn das obige XML-Beispiel wie folgt geändert wird, werden die Namespacedeklarationen richtig innerhalb des XML-Dokuments unterhalb des Gültigkeitsbereichs der anderen Namespacedeklaration weitergegeben.

<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>  

Im obigen XML-Beispiel wird das Attribut a:parent-id im parent-Element im http://www.contoso.com/parent-id-Namespace eingefügt. Die CreateAttribute-Methode wird zum Einfügen des Attributs bei Positionierung auf dem parent-Element verwendet. Die http://www.contoso.com-Namespacedeklaration wird von der XPathNavigator-Klasse automatisch eingefügt, damit die Konsistenz mit dem restlichen XML-Dokument erhalten bleibt.

Ändern von Entitätsverweisknoten

Entitätsverweisknoten in einem XmlDocument-Objekt sind schreibgeschützt und können weder mit der XPathNavigator-Klasse noch mit der XmlNode-Klasse geändert werden. Ein Versuch, einen Entitätsverweisknoten zu ändern, führt zu einer InvalidOperationException.

Ändern von xsi:nil-Knoten

Die XML-Schemaempfehlung des W3C führt das Konzept des "nillable"-Elements ein. Wenn ein Element "nillable" ist, kann das Element gültig sein, ohne einen Inhalt zu haben. Das Konzept eines "nillable"-Elements entspricht dem Konzept eines Objekts, das null ist. Das Hauptunterschied besteht darin, dass auf ein null-Objekt keinerlei Zugriff möglich ist, während ein xsi:nil-Element zwar keinen Inhalt (untergeordnete Elemente oder Text) hat, aber Eigenschaften (z. B. Attribute) aufweist, auf die zugegriffen werden kann. Wenn ein Element eines XML-Dokuments ein xsi:nil-Attribut mit dem Wert true hat, bedeutet dies, dass das Element keinen Inhalt hat.

Wenn einem gültigen Element, dessen XPathNavigator-Attribut den Wert xsi:nil hat, mittels eines true-Objekts Inhalt hinzugefügt wird, wird der Wert des xsi:nil-Attributs auf false festgelegt.

Hinweis

Wenn der Inhalt eines Elements, dessen xsi:nil-Attribut den Wert false hat, gelöscht wird, wird der Wert des Attributs nicht auf true geändert.

Speichern eines XML-Dokuments

Änderungen eines XmlDocument-Objekts, die von den in diesem Thema beschriebenen Bearbeitungsmethoden vorgenommen wurden, werden mit den Methoden der XmlDocument-Klasse gespeichert. Weitere Informationen zum Speichern der an einem XmlDocument-Objekt vorgenommenen Änderungen finden Sie unter Speichern und Ausgeben eines Dokuments.

Siehe auch