Udostępnij za pośrednictwem


Modyfikowanie danych XML przy użyciu klasy XPathNavigator

Klasa XPathNavigator udostępnia zestaw metod używanych do modyfikowania węzłów i wartości w dokumencie XML. Aby można było używać tych metod, XPathNavigator obiekt musi być edytowalny, czyli jego CanEdit właściwość musi mieć wartość true.

XPathNavigator obiekty, które mogą edytować dokument XML, są tworzone przez CreateNavigator metodę XmlDocument klasy . XPathNavigator obiekty utworzone przez klasę XPathDocument są tylko do odczytu, a każda próba użycia metod edycji obiektu utworzonego XPathNavigator przez XPathDocument obiekt powoduje wystąpienie NotSupportedExceptionobiektu .

Aby uzyskać więcej informacji na temat tworzenia obiektów edytowalnych XPathNavigator , zobacz Odczytywanie danych XML przy użyciu elementów XPathDocument i XmlDocument.

Modyfikowanie węzłów

Prostą techniką zmiany wartości węzła jest użycie SetValue metod XPathNavigator i SetTypedValue klasy .

W poniższej tabeli przedstawiono wpływ tych metod na różne typy węzłów.

XPathNodeType Zmieniono dane
Root Nieobsługiwane.
Element Zawartość elementu.
Attribute Wartość atrybutu.
Text Zawartość tekstowa.
ProcessingInstruction Zawartość, z wyłączeniem obiektu docelowego.
Comment Zawartość komentarza.
Namespace Nieobsługiwane.

Uwaga

Edytowanie Namespace węzłów lub węzłów Root nie jest obsługiwane.

Klasa XPathNavigator udostępnia również zestaw metod używanych do wstawiania i usuwania węzłów. Aby uzyskać więcej informacji na temat wstawiania i usuwania węzłów z dokumentu XML, zobacz Temat Wstawianie danych XML przy użyciu klasy XPathNavigator i Usuwanie danych XML przy użyciu klasy XPathNavigator .

Modyfikowanie nietypowych wartości

Metoda SetValue po prostu wstawia nietypową string wartość przekazaną jako parametr jako wartość węzła XPathNavigator , na który jest obecnie umieszczony obiekt. Wartość jest wstawiana bez żadnego typu lub bez sprawdzania, czy nowa wartość jest prawidłowa zgodnie z typem węzła, jeśli są dostępne informacje o schemacie.

W poniższym przykładzie SetValue metoda służy do aktualizowania wszystkich price elementów w contosoBooks.xml pliku.

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)

W przykładzie plik jest contosoBooks.xml pobierany jako dane wejściowe.

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

Modyfikowanie wpisanych wartości

Gdy typ węzła jest prostym typem schematu XML W3C, nowa wartość wstawiona przez SetTypedValue metodę jest sprawdzana względem aspektów prostego typu przed ustawieniem wartości. Jeśli nowa wartość jest nieprawidłowa zgodnie z typem węzła (na przykład ustawienie wartości -1 elementu, którego typem jest xs:positiveInteger), powoduje wyjątek.

Poniższy przykład próbuje zmienić wartość price elementu pierwszego book elementu w contosoBooks.xml pliku na DateTime wartość. Ponieważ typ schematu price XML elementu jest zdefiniowany jako xs:decimal w contosoBooks.xsd plikach, powoduje to wyjątek.

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

W przykładzie plik jest contosoBooks.xml pobierany jako dane wejściowe.

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

Przykład przyjmuje contosoBooks.xsd również jako dane wejściowe.

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

Efekty edycji silnie typiowanych danych XML

Klasa XPathNavigator używa schematu XML W3C jako podstawy do opisywania silnie typizowanego kodu XML. Elementy i atrybuty można dodawać adnotacje z informacjami o typie na podstawie weryfikacji względem dokumentu schematu XML W3C. Elementy, które mogą zawierać inne elementy lub atrybuty, są nazywane typami złożonymi, podczas gdy te, które mogą zawierać tylko zawartość tekstową, są nazywane prostymi typami.

Uwaga

Atrybuty mogą mieć tylko proste typy.

Element lub atrybut można uznać za prawidłowy schemat, jeśli jest zgodny ze wszystkimi regułami specyficznymi dla jego definicji typu. Element, który ma prosty typ xs:int , musi zawierać wartość liczbową między -2147483648 i 2147483647, aby być prawidłowym schematem. W przypadku typów złożonych ważność schematu elementu zależy od ważności schematu elementów podrzędnych i atrybutów. W związku z tym, jeśli element jest prawidłowy względem swojej złożonej definicji typu, wszystkie jego elementy podrzędne i atrybuty są prawidłowe względem ich definicji typów. Podobnie, jeśli nawet jeden z elementów podrzędnych lub atrybutów elementu jest nieprawidłowy względem jego definicji typu lub ma nieznaną ważność, element jest również nieprawidłowy lub nieznany ważność.

Biorąc pod uwagę, że ważność elementu zależy od ważności jego elementów podrzędnych i atrybutów, modyfikacje powodują zmianę ważności elementu, jeśli był wcześniej prawidłowy. W szczególności, jeśli elementy podrzędne lub atrybuty elementu są wstawiane, aktualizowane lub usuwane, ważność elementu staje się nieznana. Jest to reprezentowane przez Validity właściwość właściwości elementu SchemaInfo ustawianej na NotKnown. Ponadto efekt ten powoduje cyklicznie wzrost w dokumencie XML, ponieważ ważność elementu nadrzędnego (i jego elementu nadrzędnego itd.) również staje się nieznana.

Aby uzyskać więcej informacji na temat walidacji schematu i XPathNavigator klasy, zobacz Sprawdzanie poprawności schematu przy użyciu klasy XPathNavigator.

Modyfikowanie atrybutów

Metody SetValue i SetTypedValue mogą służyć do modyfikowania nietypowych i typowych węzłów atrybutów, a także innych typów węzłów wymienionych w sekcji "Modyfikowanie węzłów".

Poniższy przykład zmienia wartość atrybutu genre pierwszego book elementu w books.xml pliku.

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

Aby uzyskać więcej informacji na temat SetValue metod i SetTypedValue , zobacz sekcje "Modyfikowanie nietypowych wartości" i "Modyfikowanie wartości typowych".

Właściwości InnerXml i OuterXml

Właściwości InnerXmlXPathNavigator i OuterXml klasy zmieniają znaczniki XML węzłówXPathNavigator, na których obecnie znajduje się obiekt.

Właściwość InnerXml zmienia znacznik XML węzłów XPathNavigator podrzędnych, na których jest obecnie umieszczony obiekt z analizowaną zawartością danego pliku XML string. OuterXml Podobnie właściwość zmienia znacznik XML węzłów XPathNavigator podrzędnych, na których obecnie znajduje się obiekt, a także bieżący węzeł.

W poniższym przykładzie użyto OuterXml właściwości , aby zmodyfikować wartość price elementu i wstawić nowy discount atrybut w pierwszym book elemenie contosoBooks.xml w pliku.

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

W przykładzie plik jest contosoBooks.xml pobierany jako dane wejściowe.

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

Modyfikowanie węzłów przestrzeni nazw

W modelu obiektów dokumentów (DOM) deklaracje przestrzeni nazw są traktowane tak, jakby były zwykłymi atrybutami, które można wstawić, zaktualizować i usunąć. Klasa XPathNavigator nie zezwala na takie operacje w węzłach przestrzeni nazw, ponieważ zmiana wartości węzła przestrzeni nazw może zmienić tożsamość elementów i atrybutów w zakresie węzła przestrzeni nazw, jak pokazano w poniższym przykładzie.

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

Jeśli powyższy przykład XML zostanie zmieniony w następujący sposób, spowoduje to zmianę nazwy każdego elementu w dokumencie, ponieważ wartość identyfikatora URI przestrzeni nazw każdego elementu zostanie zmieniona.

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

Wstawianie węzłów przestrzeni nazw, które nie powodują konfliktu z deklaracjami przestrzeni nazw w zakresie wstawionym, jest dozwolone przez klasę XPathNavigator . W takim przypadku deklaracje przestrzeni nazw nie są deklarowane w niższych zakresach w dokumencie XML i nie powodują zmiany nazwy, jak pokazano w poniższym przykładzie.

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

Jeśli powyższy przykład XML zostanie zmieniony w następujący sposób, deklaracje przestrzeni nazw są poprawnie propagowane w dokumencie XML poniżej zakresu innej deklaracji przestrzeni nazw.

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

W powyższym przykładzie XML atrybut a:parent-id jest wstawiany do parent elementu w http://www.contoso.com/parent-id przestrzeni nazw. Metoda CreateAttribute służy do wstawiania atrybutu, gdy jest on umieszczony na elemecie parent . Deklaracja http://www.contoso.com przestrzeni nazw jest automatycznie wstawiana przez klasę XPathNavigator w celu zachowania spójności pozostałej części dokumentu XML.

Modyfikowanie węzłów odwołania do jednostek

Węzły odwołania do jednostek w XmlDocument obiekcie są tylko do odczytu i nie można ich edytować przy użyciu XPathNavigator klas lub XmlNode . Każda próba zmodyfikowania węzła odwołania do jednostki powoduje wyświetlenie elementu InvalidOperationException.

Modyfikowanie węzłów xsi:nil

Zalecenie schematu XML W3C wprowadza koncepcję elementu, który jest nillable. Gdy element jest nillable, możliwe jest, aby element nie miał zawartości i nadal był prawidłowy. Koncepcja elementu, który jest nillable, jest podobna do koncepcji obiektu będącego null. Główną różnicą null jest to, że nie można uzyskać dostępu do obiektu w żaden sposób, podczas gdy xsi:nil element nadal ma właściwości, takie jak atrybuty, do których można uzyskać dostęp, ale nie ma zawartości (elementów podrzędnych lub tekstu). Istnienie atrybutu xsi:nil z wartością true elementu w dokumencie XML służy do wskazania, że element nie ma zawartości.

XPathNavigator Jeśli obiekt jest używany do dodawania zawartości do prawidłowego elementu z xsi:nil atrybutem o wartości true, wartość jego xsi:nil atrybutu jest ustawiona na falsewartość .

Uwaga

Jeśli zawartość elementu z atrybutem ustawionym xsi:nil na false jest usuwana, wartość atrybutu nie zostanie zmieniona na true.

Zapisywanie dokumentu XML

Zapisywanie zmian wprowadzonych w XmlDocument obiekcie w wyniku metod edycji opisanych w tym temacie odbywa się przy użyciu metod XmlDocument klasy. Aby uzyskać więcej informacji na temat zapisywania zmian wprowadzonych w XmlDocument obiekcie, zobacz Zapisywanie i zapisywanie dokumentu.

Zobacz też