XML-gegevens wijzigen met XPathNavigator
De XPathNavigator klasse biedt een set methoden die worden gebruikt om knooppunten en waarden in een XML-document te wijzigen. Als u deze methoden wilt gebruiken, moet het XPathNavigator object kunnen worden bewerkt, dat wil gezegd: CanEdit de eigenschap ervan moet zijn true
.
XPathNavigator objecten die een XML-document kunnen bewerken, worden gemaakt door de CreateNavigator methode van de XmlDocument klasse. XPathNavigator objecten die door de XPathDocument klasse zijn gemaakt, zijn alleen-lezen en pogingen om de bewerkingsmethoden te gebruiken van een XPathNavigator object dat door een XPathDocument object is gemaakt, resulteert in een NotSupportedException.
Zie XML-gegevens lezen met XPathDocument en XmlDocument voor meer informatie over het maken van bewerkbare XPathNavigator objecten.
Knooppunten wijzigen
Een eenvoudige techniek voor het wijzigen van de waarde van een knooppunt is het gebruik van de SetValue en SetTypedValue methoden van de XPathNavigator klasse.
De volgende tabel bevat de effecten van deze methoden op verschillende knooppunttypen.
XPathNodeType | Gegevens gewijzigd |
---|---|
Root | Wordt niet ondersteund. |
Element | De inhoud van het element. |
Attribute | De waarde van het kenmerk. |
Text | De tekstinhoud. |
ProcessingInstruction | De inhoud, met uitzondering van het doel. |
Comment | De inhoud van de opmerking. |
Namespace | Niet ondersteund. |
De XPathNavigator klasse biedt ook een set methoden die worden gebruikt om knooppunten in te voegen en te verwijderen. Zie de onderwerpen XML-gegevens invoegen met XPathNavigator en XML-gegevens verwijderen met behulp van XPathNavigator en XPathNavigator voor meer informatie over het invoegen en verwijderen van knooppunten uit een XML-document.
Niet-getypte waarden wijzigen
Met SetValue de methode wordt de niet-getypte string
waarde ingevoegd die als parameter wordt doorgegeven als de waarde van het knooppunt waarop het XPathNavigator object momenteel is geplaatst. De waarde wordt ingevoegd zonder enig type of zonder te controleren of de nieuwe waarde geldig is volgens het type van het knooppunt als er schemagegevens beschikbaar zijn.
In het volgende voorbeeld wordt de SetValue methode gebruikt om alle price
elementen in het contosoBooks.xml
bestand bij te werken.
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 het voorbeeld wordt het contosoBooks.xml
bestand als invoer gebruikt.
<?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>
Getypte waarden wijzigen
Wanneer het type van een knooppunt een eenvoudig type W3C XML-schema is, wordt de nieuwe waarde die door de SetTypedValue methode is ingevoegd, gecontroleerd op de facetten van het eenvoudige type voordat de waarde wordt ingesteld. Als de nieuwe waarde niet geldig is op basis van het type van het knooppunt (bijvoorbeeld het instellen van een waarde van -1
een element waarvan het type is xs:positiveInteger
), resulteert deze in een uitzondering.
In het volgende voorbeeld wordt geprobeerd de waarde van het element van het price
eerste book
element in het contosoBooks.xml
bestand te wijzigen in een DateTime waarde. Omdat het XML-schematype van het price
element is gedefinieerd als xs:decimal
in de contosoBooks.xsd
bestanden, resulteert dit in een uitzondering.
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 het voorbeeld wordt het contosoBooks.xml
bestand als invoer gebruikt.
<?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 het voorbeeld wordt ook de contosoBooks.xsd
invoer gebruikt.
<?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>
De effecten van het bewerken van sterk getypte XML-gegevens
De XPathNavigator klasse maakt gebruik van het W3C XML-schema als basis voor het beschrijven van sterk getypte XML. Elementen en kenmerken kunnen worden geannoteerd met typegegevens op basis van validatie voor een W3C XML-schemadocument. Elementen die andere elementen of kenmerken kunnen bevatten, worden complexe typen genoemd, terwijl elementen die alleen tekstuele inhoud kunnen bevatten, eenvoudige typen worden genoemd.
Notitie
Kenmerken kunnen alleen eenvoudige typen hebben.
Een element of kenmerk kan als schema-geldig worden beschouwd als deze voldoet aan alle regels die specifiek zijn voor de typedefinitie. Een element met het eenvoudige type xs:int
moet een numerieke waarde bevatten tussen -2147483648 en 2147483647 om schema geldig te zijn. Voor complexe typen is de schema-geldigheid van het element afhankelijk van de schema-geldigheid van de onderliggende elementen en kenmerken. Dus als een element geldig is op basis van de complexe typedefinitie, zijn alle onderliggende elementen en kenmerken geldig voor hun typedefinities. Als zelfs een van de onderliggende elementen of kenmerken van een element ongeldig is ten opzichte van de typedefinitie of een onbekende geldigheid heeft, is het element ook ongeldig of van onbekende geldigheid.
Aangezien de geldigheid van een element afhankelijk is van de geldigheid van de onderliggende elementen en kenmerken, resulteren wijzigingen in beide elementen in een wijziging van de geldigheid van het element als het eerder geldig was. Als de onderliggende elementen of kenmerken van een element worden ingevoegd, bijgewerkt of verwijderd, wordt de geldigheid van het element onbekend. Dit wordt vertegenwoordigd door de Validity eigenschap van de eigenschap van het element SchemaInfo dat wordt ingesteld op NotKnown. Bovendien wordt dit effect recursief omhoog in het XML-document, omdat de geldigheid van het bovenliggende element (en het bovenliggende element, enzovoort) ook onbekend wordt.
Zie Schemavalidatie met behulp van XPathNavigator voor meer informatie over schemavalidatie en de XPathNavigator klasse.
Kenmerken wijzigen
De SetValue en SetTypedValue methoden kunnen worden gebruikt om niet-getypte en getypte kenmerkknooppunten te wijzigen, evenals de andere knooppunttypen die worden vermeld in de sectie 'Knooppunten wijzigen'.
In het volgende voorbeeld wordt de waarde van het kenmerk van het genre
eerste book
element in het books.xml
bestand gewijzigd.
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);
Zie de secties 'Niet-getypte waarden wijzigen' en 'Getypte waarden wijzigen' voor meer informatie over de SetValue en SetTypedValue methoden.
Eigenschappen van InnerXml en OuterXml
De InnerXml eigenschappen van OuterXml de XPathNavigator klasse wijzigen de XML-opmaak van de knooppunten waarop een XPathNavigator object momenteel is geplaatst.
De InnerXml eigenschap wijzigt de XML-opmaak van de onderliggende knooppunten waarop een XPathNavigator object momenteel is geplaatst met de geparseerde inhoud van de opgegeven XML string
. Op dezelfde manier wijzigt de OuterXml eigenschap de XML-opmaak van de onderliggende knooppunten waarop een XPathNavigator object momenteel is geplaatst, evenals het huidige knooppunt zelf.
In het volgende voorbeeld wordt de OuterXml eigenschap gebruikt om de waarde van het price
element te wijzigen en een nieuw discount
kenmerk in te voegen op het eerste book
element in het contosoBooks.xml
bestand.
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 het voorbeeld wordt het contosoBooks.xml
bestand als invoer gebruikt.
<?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>
Naamruimteknooppunten wijzigen
In het Document Object Model (DOM) worden naamruimtedeclaraties behandeld alsof ze reguliere kenmerken zijn die kunnen worden ingevoegd, bijgewerkt en verwijderd. De XPathNavigator klasse staat dergelijke bewerkingen niet toe op naamruimteknooppunten, omdat het wijzigen van de waarde van een naamruimteknooppunt de identiteit van de elementen en kenmerken binnen het bereik van het naamruimteknooppunt kan wijzigen, zoals wordt geïllustreerd in het volgende voorbeeld.
<root xmlns="http://www.contoso.com">
<child />
</root>
Als het bovenstaande XML-voorbeeld op de volgende manier wordt gewijzigd, wordt de naam van elk element in het document gewijzigd omdat de waarde van de naamruimte-URI van elk element wordt gewijzigd.
<root xmlns="urn:contoso.com">
<child />
</root>
Het invoegen van naamruimteknooppunten die niet conflicteren met naamruimtedeclaraties in het bereik waarin ze worden ingevoegd, is toegestaan door de XPathNavigator klasse. In dit geval worden de naamruimtedeclaraties niet gedeclareerd bij lagere bereiken in het XML-document en resulteert dit niet in een andere naam, zoals geïllustreerd in het volgende voorbeeld.
<root xmlns:a="http://www.contoso.com">
<parent>
<a:child />
</parent>
</root>
Als het bovenstaande XML-voorbeeld op de volgende manier wordt gewijzigd, worden de naamruimtedeclaraties correct doorgegeven in het XML-document onder het bereik van de andere naamruimtedeclaratie.
<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>
In het bovenstaande XML-voorbeeld wordt het kenmerk a:parent-id
ingevoegd op het parent
element in de http://www.contoso.com/parent-id
naamruimte. De CreateAttribute methode wordt gebruikt om het kenmerk in te voegen terwijl het op het parent
element is geplaatst. De http://www.contoso.com
naamruimtedeclaratie wordt automatisch door de XPathNavigator klasse ingevoegd om de consistentie van de rest van het XML-document te behouden.
Entiteitsverwijzingsknooppunten wijzigen
Entiteitsverwijzingsknooppunten in een XmlDocument object hebben het kenmerk Alleen-lezen en kunnen niet worden bewerkt met behulp van de XPathNavigator of XmlNode klassen. Elke poging om een entiteitsreferentieknooppunt te wijzigen, resulteert in een InvalidOperationException.
XSI:nil-knooppunten wijzigen
De aanbeveling voor het W3C XML-schema introduceert het concept van een element dat niet kan worden gebruikt. Wanneer een element niet kan worden gebruikt, is het mogelijk dat het element geen inhoud heeft en nog steeds geldig is. Het concept van een element dat nillable is, is vergelijkbaar met het concept van een object.null
Het belangrijkste verschil is dat een null
object op geen enkele manier kan worden geopend, terwijl een xsi:nil
element nog steeds eigenschappen heeft, zoals kenmerken die kunnen worden geopend, maar geen inhoud heeft (onderliggende elementen of tekst). Het bestaan van het xsi:nil
kenmerk met een waarde van true
een element in een XML-document wordt gebruikt om aan te geven dat een element geen inhoud heeft.
Als een XPathNavigator object wordt gebruikt om inhoud toe te voegen aan een geldig element met een xsi:nil
kenmerk met een waarde van true
, wordt de waarde van xsi:nil
het kenmerk ingesteld op false
.
Notitie
Als de inhoud van een element waarop een xsi:nil
kenmerk is ingesteld false
, wordt verwijderd, wordt de waarde van het kenmerk niet gewijzigd in true
.
Een XML-document opslaan
Het opslaan van wijzigingen in een XmlDocument object als gevolg van de bewerkingsmethoden die in dit onderwerp worden beschreven, wordt uitgevoerd met behulp van de methoden van de XmlDocument klasse. Zie Een document opslaan en schrijven voor meer informatie over het opslaan van wijzigingen in een XmlDocument object.