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, consultez 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 pris 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 pris 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, consultez 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
.
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)
L'exemple prend le fichier contosoBooks.xml
comme entrée.
<?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>
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("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);
L'exemple prend le fichier contosoBooks.xml
comme entrée.
<?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>
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="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>
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 du code XML fortement typé. 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.
Notes
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", "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);
L'exemple prend le fichier contosoBooks.xml
comme entrée.
<?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>
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="http://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="http://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="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>
Dans l'exemple XML ci-dessus, l'attribut a:parent-id
est inséré dans l'élément parent
dans l'espace de noms http://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 http://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
.
Notes
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, consultez Enregistrement et écriture d'un document.