OVH Cloud OVH Cloud

Modifier un fichier XML

6 réponses
Avatar
Bull
Bonjour à tous,

Je désire me passer d'access pour stocker les données de mon application.
Sur un forum, un utilisateur m'a conseillé d'utiliser le XML avec notamment
le Xpath qui permet de faire des requêtes équivalentes à SQL. J'ai regardé
rapidement, et avec cela, effectivement je devrais pouvoir faire
l'équivalent de mes select * from (mis à part le type WHERE champ LIKE
'%valeur%' que je n'ai pas encore trouvé).

Maintenant, je suis en train de regarder pour l'écriture d'un fichier XML.
J'ai trouvé l'objet XmlTextWriter qui permet sans problème d'écrire un
fichier XML en partant de 0. Mon problème maintenant se pose dans l'exemple
suivant. J'ai un fichier XML déjà existant du type :

<Items>
<Item>
<Name>Nom1</Name>
<Description>Description1</Description>
</Item>
<Item>
<Name>Nom2</Name>
<Description>Description2</Description>
</Item>
</Items>

Première question : comment ajouter l'item suivant directement à la suite :
<Item>
<Name>Nom3</Name>
<Description>Description3</Description>
</Item>

Deuxième question : comment supprimer l'item donc le <Name> vaut "Nom2" ?

Merci d'avance pour votre aide et vos réponses,
Cordialement,
Bull

6 réponses

Avatar
Zoury
Salut Bull! :O)

Pour mettre à jour un document (ou même en créer un nouveau) tu peux
employer un XmlDocument.

Ex
'***
' MainModule
Option Explicit On

Imports System.Xml
Imports System.Text

Module MainModule

Public Sub Main()

Dim sbXml As StringBuilder
Dim xd As XmlDocument
Dim xn As XmlNode

' Xml à traiter
sbXml = New StringBuilder(153)
sbXml.Append("<Items>")
sbXml.Append("<Item>")
sbXml.Append("<Name>Nom1</Name>")
sbXml.Append("<Description>Description1</Description>")
sbXml.Append("</Item>")
sbXml.Append("<Item>")
sbXml.Append("<Name>Nom2</Name>")
sbXml.Append("<Description>Description2</Description>")
sbXml.Append("</Item>")
sbXml.Append("</Items>")

' on charge le XML dans le document
xd = New XmlDocument
xd.LoadXml(sbXml.ToString())


'---------------------------------------------------------------------------
' Première question : comment ajouter l'item suivant directement à
la suite :
' <Item>
' <Name>Nom3</Name>
' <Description>Description3</Description>
' </Item>

'---------------------------------------------------------------------------
' tu peux procéder de 2 façons.
'--------------------------------------------------------
' 1. tu ajoutes le bloc de texte directement à la suite
'sbXml = New StringBuilder
'sbXml.Append(xd.DocumentElement.InnerXml)
'sbXml.Append("<Item>")
'sbXml.Append("<Name>Nom3</Name>")
'sbXml.Append("<Description>Description3</Description>")
'sbXml.Append("</Item>")
' et tu réaffectes le InnerXml du noeud racine (xd.DocumentElement)
'xd.DocumentElement.InnerXml = sbXml.ToString()
'Console.WriteLine(xd.OuterXml)
'--------------------------------------------------------
' 2. tu ajoutes des noeuds dans le document
xn = xd.DocumentElement.AppendChild(xd.CreateElement("Item"))
xn.AppendChild(xd.CreateElement("Name")).InnerText = "Nom3"
xn.AppendChild(xd.CreateElement("Decription")).InnerText "Description3"
Console.WriteLine(xd.OuterXml)



'---------------------------------------------------------------------------
' Deuxième question : comment supprimer l'item donc le <Name> vaut
"Nom2" ?

'---------------------------------------------------------------------------
' on sélectionne le noeud avec SelectSingleNode() qui accepte une
requête XPath
xn = xd.SelectSingleNode(String.Format("//Item[Name='{0}']",
"Nom2"))
xn.ParentNode.RemoveChild(xn)
Console.WriteLine(xd.OuterXml)

End Sub

End Module
'***


--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
Bull
Salut Zoury,

Merci beaucoup pour ta réponse toujours aussi complète.

Entre temps, j'ai trouvé par moi même un moyen différent de modifier les
données d'un noeud de mon xml comme suit :

Dim xpath As String = "//Folders/Folder[Id='{0}']"

Dim folderNode As XmlNode = XmlDoc.SelectSingleNode(String.Format(xpath,
idFolder))

Dim childNode As XmlNode

'on balaie tous les champs du folder

For Each childNode In folderNode.ChildNodes()

Select Case childNode.Name

Case "Title"

'on met à jour le Title

childNode.InnerText = newTitle

End Select

Next


En gros, je recherche le noeud en question, je balaie les noeuds enfant
jusqu'à trouver celui que je désire modifier (avec le select case) et une
fois trouvé, je modifie sa valeur. Cela fonctionne, mais est-ce "propre"
niveau programmation ?

Merci d'avance,
Bull


"Zoury" <yanick_lefebvre at hotmail dot com> a écrit dans le message de
news:
Salut Bull! :O)

Pour mettre à jour un document (ou même en créer un nouveau) tu peux
employer un XmlDocument.

Ex
'***
' MainModule
Option Explicit On

Imports System.Xml
Imports System.Text

Module MainModule

Public Sub Main()

Dim sbXml As StringBuilder
Dim xd As XmlDocument
Dim xn As XmlNode

' Xml à traiter
sbXml = New StringBuilder(153)
sbXml.Append("<Items>")
sbXml.Append("<Item>")
sbXml.Append("<Name>Nom1</Name>")
sbXml.Append("<Description>Description1</Description>")
sbXml.Append("</Item>")
sbXml.Append("<Item>")
sbXml.Append("<Name>Nom2</Name>")
sbXml.Append("<Description>Description2</Description>")
sbXml.Append("</Item>")
sbXml.Append("</Items>")

' on charge le XML dans le document
xd = New XmlDocument
xd.LoadXml(sbXml.ToString())


'---------------------------------------------------------------------------
' Première question : comment ajouter l'item suivant directement à
la suite :
' <Item>
' <Name>Nom3</Name>
' <Description>Description3</Description>
' </Item>

'---------------------------------------------------------------------------
' tu peux procéder de 2 façons.
'--------------------------------------------------------
' 1. tu ajoutes le bloc de texte directement à la suite
'sbXml = New StringBuilder
'sbXml.Append(xd.DocumentElement.InnerXml)
'sbXml.Append("<Item>")
'sbXml.Append("<Name>Nom3</Name>")
'sbXml.Append("<Description>Description3</Description>")
'sbXml.Append("</Item>")
' et tu réaffectes le InnerXml du noeud racine (xd.DocumentElement)
'xd.DocumentElement.InnerXml = sbXml.ToString()
'Console.WriteLine(xd.OuterXml)
'--------------------------------------------------------
' 2. tu ajoutes des noeuds dans le document
xn = xd.DocumentElement.AppendChild(xd.CreateElement("Item"))
xn.AppendChild(xd.CreateElement("Name")).InnerText = "Nom3"
xn.AppendChild(xd.CreateElement("Decription")).InnerText > "Description3"
Console.WriteLine(xd.OuterXml)



'---------------------------------------------------------------------------
' Deuxième question : comment supprimer l'item donc le <Name> vaut
"Nom2" ?

'---------------------------------------------------------------------------
' on sélectionne le noeud avec SelectSingleNode() qui accepte une
requête XPath
xn = xd.SelectSingleNode(String.Format("//Item[Name='{0}']",
"Nom2"))
xn.ParentNode.RemoveChild(xn)
Console.WriteLine(xd.OuterXml)

End Sub

End Module
'***


--
Cordialement
Yanick
MVP pour Visual Basic




Avatar
simulombula
Bonjour,

Pourquoi ne pas utiliser un dataset pour manipuler le xml ? C'est
simple et tu auras toutes les fonctionnalités fréquemment utiles. Le
seul problème possible est de bouffer trop de RAM parce que tes
fichiers XML deviennent gros, mais dans ce cas mieux vaut revenir à
une base de données.

Pierre
Avatar
Zoury
ReSalut Bull!

En gros, je recherche le noeud en question, je balaie les noeuds enfant
jusqu'à trouver celui que je désire modifier (avec le select case) et une
fois trouvé, je modifie sa valeur. Cela fonctionne, mais est-ce "propre"
niveau programmation ?



Ton code n'est pas mauvais, mais je crois que tu sous estimes la puissance
des requêtes XPath. ;O)

Les requêtes XPath te permettent de trouver ce noeud d'un seul coup (sans
boucler). Tu n'as qu'à ajouter des critères de recherche.

non testé mais le concept est là :
'***
Dim xpath As String = _
"//Folders/Folder[Id='{0}']/Items/Item[Name='{1}']"
Dim itemNode As XmlNode = _
XmlDoc.SelectSingleNode(String.Format(xpath, idFolder, itemName))
itemNode.InnerText = "mon nouveau texte"
'***

--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
Bull
ReSalut Zoury !

Ton code marche parfaitement ! Merci bien !

Par contre, dans la majeure partie des cas, je suis obligé de faire comme
j'avais fait. En effet, bien souvent, je recherche un noeud pour modifier
plusieurs de ses noeuds enfants. Avec ta méthode, il faudra que je fasse une
requête xpath par noeud enfant ce qui me parait moins rapide que ma méthode.
Par contre, j'ai utilisé ta méthode dans le cas où j'avais à modifier un
seul innerText :)

Merci beaucoup :-)
Cordialement,
Bull


"Zoury" <yanick_lefebvre at hotmail dot com> a écrit dans le message de
news:
ReSalut Bull!

En gros, je recherche le noeud en question, je balaie les noeuds enfant
jusqu'à trouver celui que je désire modifier (avec le select case) et une
fois trouvé, je modifie sa valeur. Cela fonctionne, mais est-ce "propre"
niveau programmation ?



Ton code n'est pas mauvais, mais je crois que tu sous estimes la puissance
des requêtes XPath. ;O)

Les requêtes XPath te permettent de trouver ce noeud d'un seul coup (sans
boucler). Tu n'as qu'à ajouter des critères de recherche.

non testé mais le concept est là :
'***
Dim xpath As String = _
"//Folders/Folder[Id='{0}']/Items/Item[Name='{1}']"
Dim itemNode As XmlNode = _
XmlDoc.SelectSingleNode(String.Format(xpath, idFolder, itemName))
itemNode.InnerText = "mon nouveau texte"
'***

--
Cordialement
Yanick
MVP pour Visual Basic




Avatar
Bull
Bonjour Pierre,

Je n'utilise pas de dataset pour la raison que tu évoques (RAM). Par contre,
je ne veux pas revenir à Access pour plusieurs raisons :
- la taille du fichier (j'ai gagné dans mon cas 30% taille en passant au
XML)
- temps trop long de compression de la base

Honnetement, Access n'est pas une des meilleures bases de données ;-)

Bull

a écrit dans le message de news:

Bonjour,

Pourquoi ne pas utiliser un dataset pour manipuler le xml ? C'est
simple et tu auras toutes les fonctionnalités fréquemment utiles. Le
seul problème possible est de bouffer trop de RAM parce que tes
fichiers XML deviennent gros, mais dans ce cas mieux vaut revenir à
une base de données.

Pierre