Condividi tramite


Modifica dei dati XML con XPathNavigator

La classe XPathNavigator fornisce un set di metodi usati per modificare nodi e valori in un documento XML. Per usare questi metodi, è necessario che l'oggetto XPathNavigator sia modificabile, ovvero, la relativa proprietà CanEdit deve essere true.

Gli oggetti XPathNavigator che possono modificare un documento XML vengono creati dal metodo CreateNavigator della classe XmlDocument. Gli oggetti XPathNavigator creati dalla classe XPathDocument sono di sola lettura e qualsiasi tentativo di usare i metodi di modifica di un oggetto XPathNavigator creato da un oggetto XPathDocument genererà un oggetto NotSupportedException.

Per altre informazioni sulla creazioni di oggetti XPathNavigator modificabili, vedere Lettura di dati XML con XPathDocument e XmlDocument.

Modifica dei nodi

Una tecnica semplice per modificare il valore di un nodo è quella di usare i metodi SetValue e SetTypedValue della classe XPathNavigator.

Nella tabella seguente sono elencati gli effetti di tali metodi sui diversi tipi di nodo.

XPathNodeType Dati modificati
Root Non supportato.
Element Contenuto dell'elemento.
Attribute Valore dell'attributo.
Text Contenuto di testo.
ProcessingInstruction Contenuto eccetto la destinazione.
Comment Contenuto del commento.
Namespace Non supportato.

Nota

La modifica dei nodi Namespace o del nodo Root non è supportata.

La classe XPathNavigator fornisce inoltre un set di metodi usati per inserire e rimuovere nodi. Per altre informazioni sull'inserimento e la rimozione di nodi da un documento XML, vedere gli argomenti Inserire dati XML con XPathNavigator e Rimuovere dati XML con XPathNavigator.

Modifica dei valori non tipizzati

Il metodo SetValue consente semplicemente di inserire il valore non tipizzato string, passato come parametro, come valore del nodo su cui è attualmente posizionato l'oggetto XPathNavigator. Il valore viene inserito senza alcun tipo o senza verificare la validità del nuovo valore in base al tipo del nodo se sono disponibili le informazioni sullo schema.

Nell'esempio seguente, il metodo SetValue viene usato per aggiornare tutti gli elementi price nel file contosoBooks.xml.

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)

Nell'esempio il file contosoBooks.xml viene considerato come input.

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

Modifica dei valori tipizzati

Quando il tipo di un nodo è un tipo semplice di W3C XML Schema, il nuovo valore inserito tramite il metodo SetTypedValue viene controllato rispetto ai facet del tipo semplice prima dell'impostazione del valore. Se il nuovo valore non è valido in base al tipo del nodo (ad esempio, l'impostazione di un valore -1 su un elemento il cui tipo è xs:positiveInteger), viene generata un'eccezione.

Nell'esempio seguente si tenta di modificare il valore dell'elemento price del primo elemento book nel file contosoBooks.xml in un valore DateTime. Poiché il tipo XML Schema dell'elemento price viene definito come xs:decimal nei file contosoBooks.xsd, viene generata un'eccezione.

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

Nell'esempio il file contosoBooks.xml viene considerato come input.

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

Anche il file contosoBooks.xsd viene considerato come input.

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

Effetti delle modifiche ai dati XML tipizzati in modo sicuro

La classe XPathNavigator usa W3C XML Schema come base per la descrizione del codice XML tipizzato in modo sicuro. Gli elementi e gli attributi possono essere annotati con informazioni sul tipo basate sulla convalida rispetto a un documento W3C XML Schema. Gli elementi che possono contenere altri elementi o attributi sono denominati tipi complessi, mentre gli elementi che possono contenere solo contenuto testuale sono denominati tipi semplici.

Nota

Gli attributi possono disporre solo di tipi semplici.

Un elemento o attributo può essere considerato valido per lo schema se è conforme a tutte le regole specifiche della relativa definizione del tipo. Affinché sia valido per lo schema, un elemento di tipo semplice xs:int deve contenere un valore numerico compreso tra -2147483648 e 2147483647. Per i tipi complessi, la validità di schema dell'elemento dipende dalla validità di schema dei relativi elementi e attributi figlio. Pertanto, se un elemento è valido in base alla relativa definizione di tipo complesso, tutti gli elementi e gli attributi figlio sono validi in base alle proprie definizioni dei tipi. In modo analogo, se anche un solo elemento o attributo figlio di un elemento non è valido in base alla definizione del tipo, o se la validità è sconosciuta, l'elemento sarà non valido o di validità sconosciuta.

Dato che la validità di un elemento dipende dalla validità degli elementi e attributi figlio, le modifiche apportate a entrambi determinano una modifica della validità dell'elemento in precedenza valido. In particolare, se gli elementi o attributi figlio di un elemento vengono inseriti, aggiornati o eliminati, la validità dell'elemento risulterà sconosciuta. Ciò risulterà dalla proprietà Validity della proprietà SchemaInfo dell'elemento impostata su NotKnown. Inoltre, questo effetto si estende in modo ricorsivo verso l'alto nel documento XML, poiché anche la validità dell'elemento padre dell'elemento (e del suo elemento padre e così via) risulterà sconosciuta.

Per altre informazioni sulla convalida degli schemi e sulla classe XPathNavigator, vedere Convalida dello schema con XPathNavigator.

Modifica degli attributi

I metodi SetValue e SetTypedValue possono essere usati per modificare i nodi Attribute tipizzati e non tipizzati, nonché gli altri tipi di nodo elencati nella sezione "Modifica dei nodi".

Nell'esempio seguente viene modificato il valore dell'attributo genre del primo elemento book nel file 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);  

Per altre informazioni sui metodi SetValue e SetTypedValue, vedere le sezioni "Modifica dei valori non tipizzati" e "Modifica dei valori tipizzati".

Proprietà InnerXml e OuterXml

Le proprietà InnerXml e OuterXml della classe XPathNavigator consentono di modificare il markup XML dei nodi su cui è attualmente posizionato un oggetto XPathNavigator.

La proprietà InnerXml consente di modificare il markup XML dei nodi figlio su cui è attualmente posizionato un oggetto XPathNavigator con il contenuto analizzato della string XML specificata. Allo stesso modo, la proprietà OuterXml consente di modificare il markup XML dei nodi figlio su cui è attualmente posizionato un oggetto XPathNavigator nonché il nodo corrente stesso.

Nell'esempio seguente viene usata la proprietà OuterXml per modificare il valore dell'elemento price e inserire un nuovo attributo discount sul primo elemento book nel file 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);  

Nell'esempio il file contosoBooks.xml viene considerato come input.

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

Modifica dei nodi dello spazio dei nomi

Nel DOM (Document Object Model) le dichiarazioni dello spazio dei nomi vengono considerate come attributi regolari che possono essere inseriti, aggiornati ed eliminati. Nella classe XPathNavigator tali operazioni sui nodi dello spazio dei nomi non sono consentite, in quanto la modifica del valore di un nodo dello spazio dei nomi può modificare a sua volta l'identità degli elementi e degli attributi nell'ambito del nodo dello spazio dei nomi, come illustrato nell'esempio seguente.

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

Se l'esempio precedente di codice XML viene modificato nel modo seguente, ciascun elemento del documento viene effettivamente rinominato in quanto il valore dell'URI dello spazio dei nomi di ogni singolo elemento è stato modificato.

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

La classe XPathNavigator consente l'inserimento di nodi dello spazio dei nomi che non entrino in conflitto con le dichiarazioni dello spazio dei nomi nell'ambito in cui sono stati inseriti. In questo caso, le dichiarazioni dello spazio dei nomi non sono dichiarate in ambiti inferiori nel documento XML e non determinano alcuna rinomina, come illustrato nell'esempio seguente.

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

Se l'esempio precedente di codice XML viene modificato nel modo seguente, le dichiarazioni dello spazio dei nomi vengono propagate correttamente nel documento XML nell'ambito inferiore a quello della dichiarazione dello spazio dei nomi.

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

Nell'esempio precedente di codice XML, l'attributo a:parent-id viene inserito sull'elemento parent nello spazio dei nomi http://www.contoso.com/parent-id. Il metodo CreateAttribute viene usato per inserire l'attributo quando si trova posizionato sull'elemento parent. La dichiarazione dello spazio dei nomi http://www.contoso.com viene inserita automaticamente dalla classe XPathNavigator per garantire la coerenza della parte restante del documento XML.

Modifica dei nodi dei riferimenti all'entità

I nodi dei riferimenti all'entità in un oggetto XmlDocument sono di sola lettura e non è possibile modificarli tramite le classi XPathNavigator o XmlNode. Qualsiasi tentativo di modificare un nodo dei riferimenti all'entità determinerà un'eccezione InvalidOperationException.

Modifica dei nodi xsi:nil

La raccomandazione W3C XML Schema (informazioni in lingua inglese) illustra il concetto di elemento nillable. Quando un elemento è nillable, è possibile che l'elemento non disponga di alcun contenuto pur essendo valido. Il concetto di elemento nillable è simile a quello di oggetto con valore null. La differenza principale sta tuttavia nel fatto che un oggetto null non è accessibile in alcun modo, mentre un elemento xsi:nil continua a disporre di proprietà (gli attributi, ad esempio) a cui è possibile accedere, pur non avendo alcun contenuto (elementi figlio o testo). L'esistenza dell'attributo xsi:nil con valore true su un elemento di un documento XML viene usata per indicare che un elemento è privo di contenuto.

Se un oggetto XPathNavigator viene usato per aggiungere contenuto a un elemento valido con un attributo xsi:nil e con un valore true, il valore dell'attributo xsi:nil viene impostato su false.

Nota

Se il contenuto di un elemento con un attributo xsi:nil impostato su false viene eliminato, il valore dell'attributo non verrà modificato in true.

Salvataggio di un documento XML

Il salvataggio delle modifiche apportate a un oggetto XmlDocument come risultato dei metodi di modifica descritti in questo argomento viene eseguito usando i metodi della classe XmlDocument. Per altre informazioni sul salvataggio delle modifiche apportate a un oggetto XmlDocument, vedere Salvataggio e scrittura di un documento.

Vedi anche