Dela via


Ändra XML-data med XPathNavigator

Klassen XPathNavigator innehåller en uppsättning metoder som används för att ändra noder och värden i ett XML-dokument. För att kunna använda dessa metoder XPathNavigator måste objektet vara redigerbart, dvs. dess CanEdit egenskap måste vara true.

XPathNavigator objekt som kan redigera ett XML-dokument skapas med CreateNavigator metoden för XmlDocument klassen. XPathNavigator objekt som skapats av XPathDocument klassen är skrivskyddade och alla försök att använda redigeringsmetoderna för ett XPathNavigator objekt som skapas av ett XPathDocument objekt resulterar i en NotSupportedException.

Mer information om hur du skapar redigerbara XPathNavigator objekt finns i Läsa XML-data med XPathDocument och XmlDocument.

Ändra noder

En enkel teknik för att ändra värdet för en nod är att använda SetValue klassens metoder XPathNavigator ochSetTypedValue.

I följande tabell visas effekterna av dessa metoder på olika nodtyper.

XPathNodeType Data har ändrats
Root Stöds ej.
Element Innehållet i elementet.
Attribute Värdet för attributet.
Text Textinnehållet.
ProcessingInstruction Innehållet, exklusive målet.
Comment Innehållet i kommentaren.
Namespace Stöds inte.

Kommentar

Det går inte att Root redigera Namespace noder eller noden.

Klassen XPathNavigator innehåller också en uppsättning metoder som används för att infoga och ta bort noder. Mer information om hur du infogar och tar bort noder från ett XML-dokument finns i avsnitten Infoga XML-data med XPathNavigator och Ta bort XML-data med XPathNavigator .

Ändra otypade värden

Metoden SetValue infogar helt enkelt det otypade värdet som skickas string som en parameter som värdet för noden XPathNavigator som objektet för närvarande är placerat på. Värdet infogas utan någon typ eller utan att verifiera att det nya värdet är giltigt enligt nodens typ om schemainformation är tillgänglig.

I följande exempel SetValue används metoden för att uppdatera alla price element i contosoBooks.xml filen.

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)

Exemplet tar contosoBooks.xml filen som indata.

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

Ändra inskrivna värden

När typen av en nod är en enkel W3C XML-schematyp kontrolleras det nya värdet som infogas med SetTypedValue metoden mot fasetter av den enkla typen innan värdet anges. Om det nya värdet inte är giltigt enligt nodens typ (till exempel om du anger ett värde -1 för ett element vars typ är xs:positiveInteger), resulterar det i ett undantag.

I följande exempel försöker du ändra värdet för elementet price i det första book elementet i contosoBooks.xml filen till ett DateTime värde. Eftersom XML-schematypen för elementet price definieras som xs:decimal i contosoBooks.xsd filerna resulterar detta i ett undantag.

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

Exemplet tar contosoBooks.xml filen som indata.

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

Exemplet tar contosoBooks.xsd också som indata.

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

Effekterna av redigering av starkt inskrivna XML-data

Klassen XPathNavigator använder W3C XML-schemat som grund för att beskriva starkt skriven XML. Element och attribut kan kommenteras med typinformation baserat på validering mot ett W3C XML-schemadokument. Element som kan innehålla andra element eller attribut kallas för komplexa typer, medan de som bara kan innehålla textinnehåll kallas enkla typer.

Kommentar

Attribut kan bara ha enkla typer.

Ett element eller attribut kan anses vara schema-giltigt om det överensstämmer med alla regler som är specifika för dess typdefinition. Ett element som har den enkla typen xs:int måste innehålla ett numeriskt värde mellan -2147483648 och 2147483647 vara schema-giltigt. För komplexa typer är schemats giltighet för elementet beroende av schema-giltigheten för dess underordnade element och attribut. Om ett element är giltigt mot dess komplexa typdefinition är alla dess underordnade element och attribut giltiga mot deras typdefinitioner. Om även ett av de underordnade elementen eller attributen för ett element är ogiltigt mot dess typdefinition, eller om det har en okänd giltighet, är elementet också ogiltigt eller har okänd giltighet.

Eftersom giltigheten för ett element är beroende av giltigheten för dess underordnade element och attribut, resulterar ändringar i antingen att elementets giltighet ändras om det tidigare var giltigt. Mer specifikt, om de underordnade elementen eller attributen för ett element infogas, uppdateras eller tas bort, blir elementets giltighet okänd. Detta representeras av Validity egenskapen för elementets SchemaInfo egenskap som anges till NotKnown. Dessutom ökar den här effekten rekursivt över XML-dokumentet eftersom giltigheten för elementets överordnade element (och dess överordnade element och så vidare) också blir okänd.

Mer information om schemavalidering och XPathNavigator -klassen finns i Schemavalidering med XPathNavigator.

Ändra attribut

Metoderna SetValue och SetTypedValue kan användas för att ändra otypade och inskrivna attributnoder samt andra nodtyper som anges i avsnittet "Ändra noder".

I följande exempel ändras värdet för attributet för genre det första book elementet i books.xml filen.

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

Mer information om SetValue metoderna och SetTypedValue finns i avsnitten "Ändra otypade värden" och "Ändra inskrivna värden".

Egenskaper för InnerXml och OuterXml

Egenskaperna InnerXmlXPathNavigator och OuterXml för klassen ändrar XML-markering för noderna som ett XPathNavigator objekt för närvarande är placerat på.

Egenskapen InnerXml ändrar XML-markering för de underordnade noder som ett XPathNavigator objekt för närvarande är placerat på med det tolkade innehållet i den angivna XML-koden string. OuterXml På samma sätt ändrar egenskapen XML-markeringen för de underordnade noder som ett XPathNavigator objekt för närvarande är placerat på samt själva den aktuella noden.

I följande exempel används OuterXml egenskapen för att ändra värdet för elementet price och infoga ett nytt discount attribut på det första book elementet i contosoBooks.xml filen.

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

Exemplet tar contosoBooks.xml filen som indata.

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

Ändra namnområdesnoder

I dokumentobjektmodellen (DOM) behandlas namnområdesdeklarationer som om de är vanliga attribut som kan infogas, uppdateras och tas bort. Klassen XPathNavigator tillåter inte sådana åtgärder på namnområdesnoder eftersom en ändring av värdet för en namnområdesnod kan ändra identiteten för elementen och attributen inom namnområdesnodens omfång enligt följande exempel.

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

Om XML-exemplet ovan ändras på följande sätt byter detta effektivt namn på varje element i dokumentet eftersom värdet för varje elements namnområdes-URI ändras.

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

Att infoga namnområdesnoder som inte står i konflikt med namnområdesdeklarationer i det omfång som de infogas i tillåts av XPathNavigator klassen. I det här fallet deklareras inte namnområdesdeklarationerna med lägre omfång i XML-dokumentet och resulterar inte i att namnbytet ändras enligt följande exempel.

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

Om XML-exemplet ovan ändras på följande sätt sprids namnområdesdeklarationerna korrekt i XML-dokumentet under omfånget för den andra namnområdesdeklarationen.

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

I XML-exemplet ovan infogas attributet a:parent-id i elementet parenthttp://www.contoso.com/parent-id i namnområdet. Metoden CreateAttribute används för att infoga attributet när det placeras på elementet parent . Namnområdesdeklarationen http://www.contoso.comXPathNavigator infogas automatiskt av klassen för att bevara konsekvensen i resten av XML-dokumentet.

Ändra entitetsreferensnoder

Entitetsreferensnoder i ett XmlDocument objekt är skrivskyddade och kan inte redigeras med antingen klasserna XPathNavigator eller XmlNode . Alla försök att ändra en entitetsreferensnod resulterar i en InvalidOperationException.

Ändra xsi:nil-noder

I W3C XML-schemarekommendationsrekommenditeten introduceras begreppet ett element som kan användas. När ett element är nillable är det möjligt för elementet att inte ha något innehåll och fortfarande vara giltigt. Begreppet att ett element är nillable liknar begreppet objekt som är null. Den största skillnaden är att ett null objekt inte kan nås på något sätt, medan ett xsi:nil element fortfarande har egenskaper som attribut som kan nås, men som inte har något innehåll (underordnade element eller text). Förekomsten av xsi:nil attributet med värdet true på på ett element i ett XML-dokument används för att indikera att ett element inte har något innehåll.

Om ett XPathNavigator objekt används för att lägga till innehåll i ett giltigt element med ett xsi:nil attribut med värdet trueär värdet för dess xsi:nil attribut inställt på false.

Kommentar

Om innehållet i ett element med ett xsi:nil attribut inställt på false tas bort ändras inte värdet för attributet till true.

Spara ett XML-dokument

Att spara ändringar som gjorts i ett XmlDocument objekt till följd av redigeringsmetoderna som beskrivs i det här avsnittet utförs med hjälp av klassens XmlDocument metoder. Mer information om hur du sparar ändringar som gjorts i ett XmlDocument objekt finns i Spara och skriva ett dokument.

Se även