Microsoft 365 Manipuler les données XML à partir d'Excel

  • Initiateur de la discussion Initiateur de la discussion Loulou27
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Loulou27

XLDnaute Nouveau
Bonjour,

Voilà mon sujet :
Je souhaite à partir d'excel lire les données dans un fichier XML

De ce que je comprends, le xml est potentiellement comme des répertoires => copie par un logiciel pour comprendre la structure car je n'ai aucune connaissance au sujet des xml
1768207998452.png



Ce que j'ai en tête, c'est en partant de cette référence "OR-xxxxx" (rechercher par le biais d'une feuille excel), je remonte dans le "répertoire parent" VddEcu pour ensuite rechercher d'autres référence dans les autres "sous-répertoires" pour les vérifier

J'espère avoir été compréhensif !!!

Merci pour votre aide / retour


N.B : bien sûr, j'arrive à remettre au excel le fichier xml mais cela n'est pas très pratique pour travailler dessus et je pense que le mieux est de rester en xml

Je pense que le format du fichier xml n'est pas conforme mais je ne peux pas le modifier car il vient d'un outil que j'utilise



Si je modifie l'entête du xml, j'ai du mieux

avant :
<VddDiagProjects xmlns="http://......" xmlns:xsd="http://....." xmlns:xsi="http://....." xsi:schemaLocation="http://..... http://..... http://..... >

après :
<VddDiagProjects>

Dois-je donc passer par un fichier temporaire qui prendrai le xml souhaité pour l'enregistrer dans le même format avec l'entête modifié ou y'a-t-il une astuce ?
 
Dernière édition:
Salut,
tu as un xml avec un name space (xmlns:ns) voici un code vba pour gérer ce type de xml :
VB:
Sub LireVddDiagProjects()

    Dim xml As Object                ' MSXML2.DOMDocument60
    Dim nodes As Object              ' IXMLDOMNodeList
    Dim node As Object               ' IXMLDOMNode
    Dim f As Worksheet
    Dim ligne As Long

    '--- Feuille de sortie
    Set f = ThisWorkbook.Sheets("Feuil2")
    f.Cells.Clear
    f.Range("A1:D1").Value = Array("ID OR", "Description", "Catégorie", "Paramètres")
    ligne = 2

    '--- Création du DOM (late binding)
    Set xml = CreateObject("MSXML2.DOMDocument.6.0")
    xml.async = False
    xml.validateOnParse = False

    '--- Charger le fichier XML
    If Not xml.Load("D:\Temp\VddDiag.xml") Then
        MsgBox "Erreur de chargement du XML"
        Exit Sub
    End If

    '--- Déclarer le namespace (méthode correcte MSXML)
    xml.SetProperty "SelectionNamespaces", _
        "xmlns:ns='http://example.com/vdddiag/projects'"   ' <-- adapte l’URL

    '--- Récupérer tous les nœuds OR
    Set nodes = xml.SelectNodes("//ns:OR")

    If nodes.Length = 0 Then
        MsgBox "Aucun nœud OR trouvé. Vérifie le namespace."
        Exit Sub
    End If

    '--- Parcours des OR
    For Each node In nodes

        Dim idOR As String
        Dim desc As String
        Dim cat As String
        Dim params As String

        ' ID
        idOR = node.Attributes.getNamedItem("id").Text

        ' Description
        On Error Resume Next
        desc = node.SelectSingleNode("ns:Description").Text
        On Error GoTo 0

        ' Catégorie
        On Error Resume Next
        cat = node.SelectSingleNode("ns:Category").Text
        On Error GoTo 0

        ' Paramètres
        params = LireParametres_Late(node)

        '--- Écriture dans Excel
        f.Cells(ligne, 1).Value = idOR
        f.Cells(ligne, 2).Value = desc
        f.Cells(ligne, 3).Value = cat
        f.Cells(ligne, 4).Value = params

        ligne = ligne + 1

    Next node

    MsgBox "Lecture terminée"

End Sub

'----------------------------------------------------------
' Fonction : lit tous les paramètres d’un OR (late binding)
'----------------------------------------------------------
Function LireParametres_Late(n As Object) As String

    Dim pList As Object
    Dim p As Object
    Dim txt As String

    Set pList = n.SelectNodes("ns:Parameters/ns:Parameter")

    For Each p In pList
        txt = txt & p.Attributes.getNamedItem("name").Text & "=" & p.Text & "; "
    Next p

    LireParametres_Late = txt

End Function
Ce code lit les noeuds OR et les affiche dans la feuille Feuill2 du classeur avec comme source le xml suivant :
XML:
<?xml version="1.0" encoding="UTF-8"?>
<VddDiagProjects
    xmlns="http://example.com/vdddiag/projects"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://example.com/vdddiag/projects
        http://example.com/vdddiag/projects/schema.xsd">

    <VddEcu name="ECU_Moteur" version="1.2.4">

        <OR id="OR-12345">
            <Description>Lecture des défauts moteur</Description>
            <Category>Diagnostic</Category>
            <Parameters>
                <Parameter name="Timeout" unit="ms">500</Parameter>
                <Parameter name="Retries">3</Parameter>
            </Parameters>
        </OR>

        <OR id="OR-67890">
            <Description>Effacement des défauts</Description>
            <Category>Maintenance</Category>
            <Parameters>
                <Parameter name="SecurityLevel">2</Parameter>
            </Parameters>
        </OR>

        <OR id="OR-44556">
            <Description>Lecture des valeurs en temps réel</Description>
            <Category>Mesure</Category>
            <Parameters>
                <Parameter name="SamplingRate" unit="Hz">10</Parameter>
            </Parameters>
        </OR>

    </VddEcu>

</VddDiagProjects>

VddDiag.png


A adapter La feuille , le chemin du xml source, mettre l'url (xmlns) du fichier source

Nullosse
 
Dernière édition:
Merci @nullosse

J'ai incorporé ton code; modifié les infos et ça ne fonctionnait pas mais j'ai trouvé le PB, il faut changer aussi ce que je veux rechercher (toi, tu as pris OR) donc je continue de modifier pour adapter à mon besoin mais au moins, je sais comment lire les infos dans un fichier xml

Encore MERCI
 
Merci @nullosse

J'ai incorporé ton code; modifié les infos et ça ne fonctionnait pas mais j'ai trouvé le PB, il faut changer aussi ce que je veux rechercher (toi, tu as pris OR) donc je continue de modifier pour adapter à mon besoin mais au moins, je sais comment lire les infos dans un fichier xml

Encore MERCI
Salut,
si tu n'y arrives pas mais moi ton fichier xml ou un échantillon en pièce jointe , si il n'y a pas de données confidentielles dedans, le problème peut venir de quoi mettre dans le selectnodes (une requête XPath) . Dis moi alors ce que tu cherches à extraire.
 
bonjous à tous
Les schémas sont une vraie plaie pour le microsoft.xmldom
AUTANT LES SUPPRIMER DES LE DEPART
voici une fonction issue de mon creatorRibbonX et adapt&e au tout venant qui te permet de loader le xml sans ses shemas
en nettoyant la balise

lancée par la sub test dans la quelle apres tu peux travailler ton document en DOM ou Xpath comme tu veux
VB:
Option Explicit
Sub test()
    Dim DocXML As Object
    Set DocXML = GetXmlDocument("customUI") 'remplacer customUI par le nom de la balise à nettoyer
   
    'maintenant tu travaille sur ton document xml ici
    'exemple on affiche le code
    If Not DocXML Is Nothing Then
        MsgBox DocXML.XML
        'ici tu peux travailler en DOM ou xpath comme tu veux
       
    End If
End Sub

Function GetXmlDocument(balise_A_nettoyer) As Object
    Dim xmlfile, CodEoUI, balise, apres, entre, Dc
   
    'ouvre une boite de dialogue de selection de fichier xml
    xmlfile = Application.GetOpenFilename("XML Files (*.xml), *.xml", 1, "ouvrir un fichier")
    If xmlfile = False Then Exit Function
   
    'ouverture du fichier en text
    With CreateObject("ADODB.Stream")
        .Type = 2: .Charset = "utf-8": .Open: .LoadFromFile xmlfile: CodEoUI = .ReadText(-1): .Close
    End With
   
    'on supprime tout les shemas
    If InStr(CodEoUI, "xmlns") > 0 Then
        apres = Split(CodEoUI, "<" & balise_A_nettoyer)(1)
        entre = Split(apres, ">")(0)
       CodEoUI = Replace(CodEoUI, entre, "")
    End If
   
    'et enfin on load le document dans un xmlDomDocument
    Set Dc = CreateObject("Microsoft.XMLDOM")
    With Dc
        .async = False: .validateOnParse = False: .resolveExternals = False
       
        .LoadXML CodEoUI
       
        ' si erreur xml on a la definition complete de l'erreur
        If .parseError.ErrorCode <> 0 Then
            MsgBox _
         "Erreur XML !" & vbCrLf & vbCrLf & _
         "Raison : " & .parseError.Reason & vbCrLf & _
         "Ligne : " & .parseError.Line & vbCrLf & _
         "Colonne : " & .parseError.LinePos & vbCrLf & vbCrLf & _
         "Texte :" & vbCrLf & .parseError.SrcText, _
         vbCritical, "ParseError"
           
            Exit Function
        End If
        Set GetXmlDocument = Dc
    End With
End Function
par exemple ici j'ai volontairement supprimer un">" de cloture de balise dans un fichier xml et voici le resultat
1768302383094.png

le message te dis exactement ou est l'erreur
n'ayant pas ton fichier je ne peux t'en dire plus

Patrick
 
Dernière édition:
Salut,
si tu n'y arrives pas mais moi ton fichier xml ou un échantillon en pièce jointe , si il n'y a pas de données confidentielles dedans, le problème peut venir de quoi mettre dans le selectnodes (une requête XPath) . Dis moi alors ce que tu cherches à extraire.
Effectivement, j'ai réussi en modifiant le SelectNodes et les SelectSingleNode

Je pense que ce que je n'avais pas compris, c'est que même si on passe les nodes 1 à 1 (For Each node In nodes); il fallait quand même donner le "chemin" des donneés à extraire

J'avance, c'est le principal

Merci
 
re
j'ai repris l'exemple xml de @nullose
et voici comment on travaille en DOM
Tout ce passe dans la sub test
la fonction GetXmlDocument n'est la que pour créer un domdocument sans namespace

VB:
Option Explicit
Sub test()
    Feuil1.UsedRange.ClearContents
    Dim DocXML As Object, lesOr, elements, I&, c, ChilDs, parametres, parametre, elem, DonéeParam, paramchild, e, tm
    Set DocXML = GetXmlDocument("VddDiagProjects") 'remplacer customUI par le nom de la balise à nettoyer
    'maintenant tu travaille sur ton document xml ici
    'exemple on affiche le code
    If Not DocXML Is Nothing Then
        Cells(1, 1).Resize(, 4) = Array("id des OR", "Description", "Categorie", "Paramètres") 'les entetes de tableau
        'ici tu peux travailler en DOM ou xpath comme tu veux
        'en dom
        Set lesOr = DocXML.getelementsbytagname("OR") 'selectionne toutes les balises("OR")
        I = 1
        For Each elements In lesOr 'on boucle sur toutes les balises
            I = I + 1
            c = 1
            Feuil1.Cells(I, 1) = elements.getattribute("id") 'l identifient(id)
            c = c + 1: Feuil1.Cells(I, c) = elements.getelementsbytagname("Description")(0).Text 'l 'enfant description de chaque balise or
            c = c + 1: Feuil1.Cells(I, c) = elements.getelementsbytagname("Category")(0).Text 'enfant category de chaque balise or
            
            'on compile les données des  parametres(il peut y en avoir plusieurs)
            Set parametres = elements.getelementsbytagname("Parameter")
            c = 4
            For e = 0 To parametres.Length - 1
                
                Feuil1.Cells(I, c) = Feuil1.Cells(I, c) & parametres(e).getattribute("name") & ";" & parametres(e).Text & ";"
            Next
        Next
        
    End If
End Sub

Function GetXmlDocument(balise_A_nettoyer) As Object
    Dim xmlfile, CodEoUI, balise, apres, entre, Dc
    
    'ouvre une boite de dialogue de selection de fichier xml
    xmlfile = Application.GetOpenFilename("XML Files (*.xml), *.xml", 1, "ouvrir un fichier")
    If xmlfile = False Then Exit Function
    
    'ouverture du fichier en text
    With CreateObject("ADODB.Stream")
        .Type = 2: .Charset = "utf-8": .Open: .LoadFromFile xmlfile: CodEoUI = .ReadText(-1): .Close
    End With
    
    'on supprime tout les shemas
    If InStr(CodEoUI, "xmlns") > 0 Then
        apres = Split(CodEoUI, "<" & balise_A_nettoyer)(1)
        entre = Split(apres, ">")(0)
        CodEoUI = Replace(CodEoUI, entre, "")
    End If
    
    'et enfin on load le document dans un xmlDomDocument
    Set Dc = CreateObject("Microsoft.XMLDOM")
    With Dc
        .async = False: .validateOnParse = False: .resolveExternals = False
        
        .LoadXML CodEoUI
        
        ' si erreur xml on a la definition complete de l'erreur
        If .parseError.ErrorCode <> 0 Then
            MsgBox _
         "Erreur XML !" & vbCrLf & vbCrLf & _
         "Raison : " & .parseError.Reason & vbCrLf & _
         "Ligne : " & .parseError.Line & vbCrLf & _
         "Colonne : " & .parseError.LinePos & vbCrLf & vbCrLf & _
         "Texte :" & vbCrLf & .parseError.SrcText, _
         vbCritical, "ParseError"
            
            Exit Function
        End If
        Set GetXmlDocument = Dc
    End With
End Function
demo4.gif
 
re
y a t-il un moyen d'avoir un echantillon xml?


Bonjour,

J'ai fait un fichier light

Le problème rencontré est au niveau de vddFile car quand il y a en a plusieurs, j'ai voulu passé par une boucle mais ça ne marche pas donc je suis passé par des if mais bon, si vous avez un truc mieux


La partie du prog pour cela

' MESSAGERIE
On Error Resume Next
'/a:vddDiagSpecifications/a:VddDiagSpecification/a:VddArticle/a:vddFiles/a:VddFile/a:fileName
'File ODX
i = 0
For i = 1 To node.SelectNodes("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile").Length 'Each List In nb
If node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[1]/ns:typeFile").Text = "ODX 2.0.1" Then
MESSAGERIE = node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[1]/ns:fileName").Text
ElseIf i = 2 Then
MESSAGERIE = node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[2]/ns:fileName").Text
End If
Next i
On Error GoTo 0

En fait, je voudrais extraire la donnée
node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[2]/ns:fileName").Text
quand
node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[1]/ns:typeFile").Text = "ODX 2.0.1"

si je mets
node.SelectSingleNode("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[i]/ns:fileName").Text


1768377236382.png
 

Pièces jointes

Salut,
avec un XPATH adequate cela est beaucoup plus facile :
VB:
Sub LireVddDiagProjects()
    Dim xml As Object                ' MSXML2.DOMDocument60
    Dim nodes As Object              ' IXMLDOMNodeList
    Dim node As Object               ' IXMLDOMNode
    '--- Création du DOM (late binding)
    Set xml = CreateObject("MSXML2.DOMDocument.6.0")
    xml.async = False
    xml.validateOnParse = False
    '--- Charger le fichier XML
    If Not xml.Load("D:\Temp\P64_EUROPE_CONF_17_33 - light.xml") Then
        MsgBox "Erreur de chargement du XML"
        Exit Sub
    End If
    '--- Déclarer le namespace (méthode correcte MSXML)
    xml.SetProperty "SelectionNamespaces", _
        "xmlns:ns='http://example.com/vdddiag/projects'"   ' <-- adapte l’URL
    '--- Récupérer tous les nœuds VddFile
    Set nodes = xml.SelectNodes("//ns:VddFile[ns:typeFile='ODX 2.0.1']")
    If nodes.Length = 0 Then
        MsgBox "Aucun nœud trouvé. Vérifie le namespace."
        Exit Sub
    End If
    '--- Parcours des noeuds
    For Each node In nodes
        Debug.Print node.SelectSingleNode("ns:typeFile").Text, node.SelectSingleNode("ns:fileName").Text
    Next node

    MsgBox "Lecture terminée"
End Sub
Attention dans le Xml que tu as fourni j'ai modifié ton vddDiagProject pour avoir des attributs cohérents (pas de xxxxxx)
XML:
<VddDiagProjects
    xmlns="http://example.com/vdddiag/projects"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://example.com/vdddiag/projects
        http://example.com/vdddiag/projects/schema.xsd">  <VddDiagProject>

tout est dans le :
Code:
  Set nodes = xml.SelectNodes("//ns:VddFile[ns:typeFile='ODX 2.0.1']")
le // c'est pour que la recherche s'effectue n'importe où ( pas de chemin complet) et le [] permet de spécifier une condition (un filtre)
voici ce que j'obtiens avec mon code :
ODX 2.0.1 AAS~AAS_0000004160_06_7_0.pdx
ODX 2.0.1 ALARM~MUS3_0000003886_02_1_2.pdx
ODX 2.0.1 BTEL~IVI-HEAD-UNIT-R2_0000004005_26_28_0.pdx
Nullosse
 
Bonjour,

Merci

Après, j'ai mis le chemin complet car comme il y a des chemin qui ont la même fin mais pas le même début, j'aurai des donneés non souhaitées et de plus, à chaque noeud, il faut que je récupère les données (saut de ligne quand vide) car sinon, j'ai plusieurs colonne mais pas avec le même nombre des données retournées (les sauts de ligne ne sont pas fait)

J'avance à petit pas de mon coté et à grand pas grace à vos retours, vous êtres au TOP
 
Bon,

J'ai réussi à avancer mais un PB à contourner si possible mais sinon, j'ai fait un truc qui marche

Comment peut-on faire pour repartir d'un noeud pour en faire un autre

Set nodes = xml.SelectNodes("//ns:VddEcu")
For Each node In nodes


Set ODX = node.SelectNodes("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[ns:typeFile='ODX 2.0.1']") => OK


Set mess_node = node.SelectNodes("ns:vddDiagSpecifications/ns:VddDiagSpecification")
Set ODX = mess_node.SelectNodes("ns:VddArticle/ns:vddFiles/ns:VddFile[ns:typeFile='ODX 2.0.1']") => NOK



Merci encore pour votre participation
 
Bon,

Comment peut-on faire pour repartir d'un noeud pour en faire un autre

Set nodes = xml.SelectNodes("//ns:VddEcu")
For Each node In nodes


Set ODX = node.SelectNodes("ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[ns:typeFile='ODX 2.0.1']") => OK


Set mess_node = node.SelectNodes("ns:vddDiagSpecifications/ns:VddDiagSpecification")
Set ODX = mess_node.SelectNodes("ns:VddArticle/ns:vddFiles/ns:VddFile[ns:typeFile='ODX 2.0.1']") => NOK
c'est normal que cela ne fonctionne pas : node.SelectNodes renvoit une collection de noeuds , pas un noeud . Pour récupérer un seul noeud il faut utiliser un SelectSingleNode.
Je ne comprend pas :
1 - Ta boucle alors qu'avec un :
XML:
 Set ODX = node.SelectNodes("//ns:vddDiagSpecifications/ns:VddDiagSpecification/ns:VddArticle/ns:vddFiles/ns:VddFile[ns:typeFile='ODX 2.0.1']")
tu te récupères directement les noeuds que tu veux
2 - Pourquoi tu veux la deuxième syntaxe avec un noeud intermédiaire ?
 
avec ma fonction document sans namespace
la sub serait (pour recupérer les filName de chaques VddFile)
VB:
Sub test()
    Feuil1.UsedRange.ClearContents
    Dim DocXML As Object, lesOr, elements, I&, c, ChilDs, parametres, parametre, elem, DonéeParam, paramchild, e, tm
    Set DocXML = GetXmlDocument("VddDiagProjects") 'remplacer customUI par le nom de la balise à nettoyer
    'maintenant tu travaille sur ton document xml ici
    'exemple on affiche le code
    If Not DocXML Is Nothing Then
        'ici tu peux travailler en DOM ou xpath comme tu veux
        'en dom
        Set vddfiles = DocXML.getelementsbytagname("VddFile") 'selectionne toutes les balises("VddFile")
        If vddfiles.Length > 0 Then
        For Each v In vddfiles
        Debug.Print v.getelementsbytagname("fileName")(0).Text
        Next
        End If
    End If
End Sub

1768413286277.png

quand tu en auras marre de ramer avec Xpath que tu seras prêt a travailler en DOm tu viendras me voir.
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
1
Affichages
2 K
Retour