Partager via


Modification de données XML à l'aide de XPathNavigator

La classe XPathNavigator fournit un ensemble de méthodes permettant de modifier les nœuds et les valeurs d'un document XML. Pour pouvoir utiliser ces méthodes, vous devez pouvoir modifier l'objet XPathNavigator, ce qui signifie que sa propriété CanEdit doit être true.

Les objets XPathNavigator qui permettent d'éditer un document XML sont créés par la méthode CreateNavigator de la classe XmlDocument. Les objets XPathNavigator créés par la classe XPathDocument sont en lecture seule et toute tentative d'utilisation des méthodes de modification d'un objet XPathNavigator créé par un objet XPathDocument se traduit par un objet NotSupportedException.

Pour plus d'informations sur la création d'objets XPathNavigator modifiables, voir Lecture de données XML à l'aide de XPathDocument et XmlDocument.

Modification de nœuds

Une technique simple de modification de la valeur d'un nœud consiste à utiliser les méthodes SetValue et SetTypedValue de la classe XPathNavigator.

Le tableau suivant répertorie les effets de ces méthodes sur différents types de nœuds.

XPathNodeType

Données modifiées

Root

Non prise en charge.

Element

Contenu de l'élément.

Attribute

Valeur de l'attribut.

Text

Texte.

ProcessingInstruction

Contenu, cible exclue.

Comment

Contenu du commentaire.

Namespace

Non prise en charge.

RemarqueRemarque

La modification des nœuds Namespace ou Root n'est pas prise en charge.

La classe XPathNavigator fournit également un ensemble de méthodes permettant d'insérer et de supprimer des nœuds. Pour plus d'informations sur l'insertion et la suppression de nœuds d'un document XML, voir les rubriques Insertion de données XML à l'aide de XPathNavigator et Suppression de données XML à l'aide de XPathNavigator.

Modification de valeurs non typées

La méthode SetValue insère simplement la valeur string non typée transmise sous la forme d'un paramètre comme la valeur du nœud sur lequel l'objet XPathNavigator est actuellement positionné. La valeur est insérée sans type ou sans vérifier que la nouvelle valeur est valide par rapport au type de nœud si les informations sur le schéma sont disponibles.

Dans l'exemple suivant, la méthode SetValue permet de mettre à jour tous les éléments price du fichier contosoBooks.xml.

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", "https://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)
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("bk", "https://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);
XmlDocument^ document = gcnew XmlDocument();
document->Load("contosoBooks.xml");
XPathNavigator^ navigator = document->CreateNavigator();

XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(navigator->NameTable);
manager->AddNamespace("bk", "https://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);

L'exemple prend le fichier contosoBooks.xml comme entrée.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="https://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>

Modification de valeurs typées

Si le type d'un nœud est un type simple des schémas XML du W3C, la nouvelle valeur insérée par la méthode SetTypedValue est vérifiée par rapport aux facettes du type simple avant d'être définie. Si la nouvelle valeur n'est pas valide par rapport au type du nœud (par exemple, une valeur est définie sur -1 pour un élément dont le type est xs:positiveInteger), une exception se produit.

L'exemple suivant tente de modifier la valeur de l'élément price du premier élément book du fichier contosoBooks.xml en valeur DateTime. Étant donné que le type de schéma XML de l'élément price est défini comme xs:decimal dans les fichiers contosoBooks.xsd, une exception se produit.

Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.Schemas.Add("https://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", "https://www.contoso.com/books")
navigator.MoveToChild("book", "https://www.contoso.com/books")
navigator.MoveToChild("price", "https://www.contoso.com/books")

navigator.SetTypedValue(DateTime.Now)
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("https://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", "https://www.contoso.com/books");
navigator.MoveToChild("book", "https://www.contoso.com/books");
navigator.MoveToChild("price", "https://www.contoso.com/books");

navigator.SetTypedValue(DateTime.Now);

L'exemple prend le fichier contosoBooks.xml comme entrée.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="https://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>

L'exemple prend également le fichier contosoBooks.xsd comme entrée.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="https://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>

Effets de la modification de données XML fortement typées

La classe XPathNavigator se base sur le schéma XML du W3C pour décrire des données XML fortement typées. Les éléments et les attributs ne peuvent pas être annotés avec les informations sur le type en fonction de la validation par rapport au document du W3C sur les schémas XML. Les éléments pouvant contenir d'autres éléments ou attributs sont appelés types complexes, tandis que ceux qui ne peuvent avoir que du contenu textuel sont appelés types simples.

RemarqueRemarque

Les attributs ne peuvent avoir que des types simples.

Un élément ou attribut peut être considéré comme valide pour le schéma s'il est conforme à toutes les règles spécifiques à sa définition de type. Un élément ayant le type simple xs:int doit contenir une valeur numérique comprise entre -2147483648 et 2147483647 pour être valide pour le schéma. Pour les types complexes, la validité de l'élément pour le schéma dépend de la validité pour le schéma de ses attributs et éléments enfants. Donc, si un élément est valide par rapport à sa définition de type complexe, tous ses attributs et éléments enfants sont valides par rapport à leur définition de type. De même, si un seul attribut ou élément enfant d'un élément n'est pas valide par rapport à sa définition de type ou dispose d'une validité inconnue, l'élément est également non valide ou de validité inconnue.

Étant donné que la validité d'un élément dépend de la validité de ses attributs et éléments enfants, les modifications apportées à l'un ou à l'autre se traduisent par une altération de la validité de l'élément s'il était précédemment valide. En particulier, si les attributs ou les éléments enfants d'un élément sont insérés, mis à jour ou supprimés, la validité de l'élément devient inconnue. Elle est représentée par la propriété Validity de la propriété SchemaInfo de l'élément définie sur NotKnown. En outre, cet effet se répercute vers le haut de manière récursive dans le document XML car la validité de élément parent de l'élément (et de son élément parent, etc.) devient également inconnue.

Pour plus d'informations sur la validation de schémas et la classe XPathNavigator, voir Validation de schéma à l'aide de XPathNavigator.

Modification d'attributs

Les méthodes SetValue et SetTypedValue peuvent permettre de modifier des nœuds d'attribut typés et non typés, ainsi que les autres types de nœuds d'attribut répertoriés dans la section sur la modification de nœuds.

L'exemple suivant modifie la valeur de l'attribut genre du premier élément book du fichier 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);

Pour plus d'informations sur les méthodes SetValue et SetTypedValue, voir les sections sur la modification de valeurs non typées et de valeurs typées.

Propriétés InnerXml et OuterXml

Les propriétés InnerXml et OuterXml de la classe XPathNavigator modifient le balisage XML des nœuds sur lesquels un objet XPathNavigator est actuellement positionné.

La propriété InnerXml modifie le balisage XML des nœuds enfants sur lesquels un objet XPathNavigator est actuellement positionné avec le contenu analysé de la string XML donnée. De même, la propriété OuterXml modifie le balisage XML des nœuds enfants sur lesquels un objet XPathNavigator est actuellement positionné, ainsi que le nœud actuel proprement dit.

L'exemple suivant utilise la propriété OuterXml pour modifier la valeur de l'élément price et insérer un nouvel attribut discount dans le premier élément book du fichier contosoBooks.xml.

Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml");
Dim navigator As XPathNavigator = document.CreateNavigator()

navigator.MoveToChild("bookstore", "https://www.contoso.com/books")
navigator.MoveToChild("book", "https://www.contoso.com/books")
navigator.MoveToChild("price", "https://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", "https://www.contoso.com/books");
navigator.MoveToChild("book", "https://www.contoso.com/books");
navigator.MoveToChild("price", "https://www.contoso.com/books");

navigator.OuterXml = "<price discount=\"0\">10.99</price>";

navigator.MoveToRoot();
Console.WriteLine(navigator.OuterXml);

L'exemple prend le fichier contosoBooks.xml comme entrée.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="https://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>

Modification de nœuds d'espace de noms

Dans le DOM (Document Object Model), les déclarations d'espaces de noms sont traitées comme des attributs réguliers qui peuvent être insérés, mis à jour et supprimés. La classe XPathNavigator n'autorise pas ce type d'opération sur les nœuds d'espace de noms car toute modification de la valeur d'un nœud d'espace de noms peut modifier l'identité des éléments et attributs dans la portée du nœud d'espace de noms comme illustré dans l'exemple suivant.

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

Si l'exemple XML ci-dessus est modifié de la manière suivante, chaque élément est effectivement renommé dans le document car la valeur de l'URI d'espace de noms de chaque élément est modifiée.

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

L'insertion d'espaces de noms n'entrant pas en conflit avec les déclarations d'espaces de noms dans la portée dans laquelle ils sont insérés est autorisée par la classe XPathNavigator. Dans ce cas, les déclarations d'espaces de noms ne sont pas déclarées dans des portées inférieures du document XML et ne se traduisent pas par l'attribution d'un nouveau nom comme illustré dans l'exemple suivant.

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

Si l'exemple XML ci-dessus est modifié de la manière suivante, les déclarations d'espaces de noms sont correctement propagées dans le document XML sous la portée de l'autre déclaration d'espace de noms.

<root xmlns:a="https://www.contoso.com">
    <parent a:parent-id="1234" xmlns:a="https://www.contoso.com/parent-id">
        <a:child xmlns:a="https://www.contoso.com/">
    </parent>
</root>

Dans l'exemple XML ci-dessus, l'attribut a:parent-id est inséré dans l'élément parent dans l'espace de noms https://www.contoso.com/parent-id. La méthode CreateAttribute permet d'insérer l'attribut tout en étant positionné sur l'élément parent. La déclaration d'espace de noms https://www.contoso.com est automatiquement insérée par la classe XPathNavigator pour conserver la cohérence du reste du document XML.

Modification de nœuds de référence d'entité

Les nœuds de référence d'entité d'un objet XmlDocument sont en lecture seule et ne peuvent pas être modifiés à l'aide des classes XPathNavigator ou XmlNode. Toute tentative de modification d'un nœud de référence d'entité se traduit par un objet InvalidOperationException.

Modification de nœuds xsi:nil

La recommandation du W3C sur les schémas XML introduit le concept d'élément pouvant prendre la valeur null. Si un élément peut prendre la valeur null, il peut n'avoir aucun contenu et rester valide. Le concept d'élément pouvant prendre la valeur null est similaire à celui d'objet null. La principale différence est qu'il est possible d'accéder à un objet null de n'importe quelle manière, tandis qu'un élément xsi:nil possède toujours des propriétés telles que des attributs accessibles, mais n'ayant aucun contenu (texte ou éléments enfants). L'existence de l'attribut xsi:nil présentant la valeur true dans un élément d'un document XML permet d'indiquer qu'un élément n'a aucun contenu.

Si un objet XPathNavigator permet d'ajouter du contenu à un élément valide avec un attribut xsi:nil ayant la valeur true, la valeur de son attribut xsi:nil est définie sur false.

RemarqueRemarque

Si le contenu d'un élément possédant un attribut xsi:nil défini sur false est supprimé, la valeur de l'attribut n'est pas modifiée en true.

Enregistrement d'un document XML

L'enregistrement des modifications apportées à un objet XmlDocument suite aux méthodes de modification décrites dans cette rubrique s'effectue à l'aide des méthodes de la classe XmlDocument. Pour plus d'informations sur l'enregistrement des modifications apportées à un objet XmlDocument, voir Enregistrement et écriture d'un document.

Voir aussi

Référence

XmlDocument

XPathDocument

XPathNavigator

Concepts

Traitement des données XML à l'aide du modèle de données XPath

Insertion de données XML à l'aide de XPathNavigator

Suppression de données XML à l'aide de XPathNavigator