Acces aux valeurs dans un xml [Résolu]

Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
- - Dernière réponse : Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
- 17 mai 2019 à 20:21
Bonjour,

Je suis sous vb.net et je cherche a extraire des valeurs d'un fichier xml. J'arrive à récupérer 2 des 3 valeurs que j'ai besoin.
Le xml est de cette forme:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="styles/fixture+layer+layers@html@default.xsl"?>
<?xml-stylesheet type="text/xsl" href="styles/fixture+layer+layers@csv.xsl" alternate="yes"?>
<MA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.malighting.de/grandma2/xml/MA" xsi:schemaLocation="http://schemas.malighting.de/grandma2/xml/MA http://schemas.malighting.de/grandma2/xml/3.6.1/MA.xsd" major_vers="3" minor_vers="6" stream_vers="1">
<Info datetime="2019-04-01T09:20:42" showfile="macbeth-test" />
<Layers index="3">
<Layer index="1" name="gradateurs">
<Fixture index="0" name="Dim 68" fixture_id="68" channel_id="68">
<FixtureType name="2 Dimmer 00">
<No>2</No>
</FixtureType>
<SubFixture index="0" react_to_grandmaster="true" color="ffffff">
<Patch>
<Address>143</Address>
</Patch>
<AbsolutePosition>
<Location x="0" y="0" z="0" />
<Rotation x="0" y="-0" z="0" />
<Scaling x="1" y="1" z="1" />
</AbsolutePosition>
<Channel index="0" />
</SubFixture>
</Fixture>


Voila ce que j'ai codé:


Dim cpo_patch As XDocument = XDocument.Load(Lbl_patch.Text)
Dim popatch As XElement = cpo_patch.Root.<Layers>.FirstOrDefault
Dim listPatch As IEnumerable(Of XElement) = popatch.Elements()

For Each listfixture In listPatch

If listfixture.HasElements Then

Dim Fixtures As IEnumerable(Of XElement) = listfixture.Elements

Dim u As Integer = 0

For Each fixture In Fixtures

If fixture.HasElements Then

Tbl_Patch(u, 0) = fixture.@<channel_id>
Tbl_Patch(u, 1) = fixture.<fixturetype>.@<name>
Tbl_Patch(u, 2) = fixture.@<name>

MsgBox(Tbl_Patch(u, 0) & " / " & Tbl_Patch(u, 1) & " / " & Tbl_Patch(u, 2))

End If
Next

End If

Next


ce qui marche pas c'est fixture.<FixtureType>.@<name>

Avez vous des idées sur ce qui ne va pas ?
Afficher la suite 

20/88 réponses

Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
oui bien sur
            MesPresets = (
            From f In xDoc.Descendants("Preset")
            Select New Presets With
             {
                .Name = f.Attribute("name")?.Value,
                .SpecialUse = f.Attribute("SpecialUse")?.Value,
                .Channels = (From s In f.Descendants("channels")
                             Select New Channels With
                    {
                                 .PresetValue = (From t In s.Descendants("PresetValue")
                                                 Select New Channel With
              {
                                                     .Fixture_id = t.Element("channel").Attribute("Fixture_Id")?.Value,
                                                     .Attribute_Name = t.Element("Channel").Attribute("Attribute_Name")?.Value
             ))}).ToList()}).ToList()}).Tolist()
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Dans tes classes, tu as défini des tableaux, et dans la requêtes, tu charges des listes.
Soit tu mets des listes dans tes classes, soit tu castes en tableau, avec ToArray()
Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Je me suis inspiré de ce que tu m'as envoyé hier. Apparemment je l'ai mal réutilisé.
Il vaut mieux passer par des listes ou des tableaux ?
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Toutes les collections (y'en a un paquet en .Net) dérivées des listes chainées ont ce gros avantage par rapport à un tableau de pouvoir ajouter un item (à la fin), de pouvoir insérer un item (à un index précis) ou de pouvoir enlever un item "sans laisser de trou" et tout ça sans variable tampon et dans un délai d'exécution extrêmement rapide (quelques "ticks"). Par extension, les algorithmes de tris sont aussi beaucoup plus rapides.

Tu vas me dire y'a ReDim, oui, mais redim est long et couteux en ressources système, d'ailleurs il n'existe par en C#, c'est une des "tolérance" de VB.Net, importée de VB6 et VBA.

Par défaut, j'utilise toujours une liste chainée, sauf quand je dois passer mes datas en paramètre à une méthode qui ne prends qu'un tableau en entrée. Mais dans ce cas, la plupart du temps, je fais un ToArray() au moment opportun.

Après je suis autodidacte, mon apprentissage est incomplet et empirique, du coup ça vaut ce que ça vaut.

Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Ok,
du coup dans mes classes, pour déclarer des listes il faut que je supprime les parenthèses ?
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Haaaa, ta remarque me fais prendre conscience de ma boulette
J'ai codé en C# (que je maitrise mieux) et utilisé un traducteur et j'ai pas fait attention aux parenthèses....
Ce qui est même surprenant c'est que les codes que je t'ai donnés ont fonctionné.

Bref, message 11, puis 19, la classe Fixture mieux écrite
Class Fixture
    Public Property Nom As String'là c'est bien une string unique

    Public Property Type As String

    Public Property NomType As String

    Public Property LesSubFixtures As List(Of SubFixture)'là c'est une liste 
End Class


Et les deux autres
Class SubFixture
    Public Property PatchAdresse As Integer

    Public Property Position As Point3D

    Public Property Rotation As Point3D

    Public Property Echelle As Point3D
End Class

Class Point3D
    Public Property X As Double

    Public Property Y As Double

    Public Property Z As Double

    ''' <summary>
    ''' Cette méthode évite d'écrire 3fois la même chose dans la requete de désserialisation
    ''' </summary>
    ''' <param name="E"></param>
    ''' <returns></returns>
    Public Shared Function FromXML(ByVal E As XElement) As Point3D
        If E Is Nothing Then
            Return New Point3D()
        End If

        Return New Point3D With {.X = ToDouble(E.Attribute("x")?.Value), .Y = ToDouble(E.Attribute("y")?.Value), .Z = ToDouble(E.Attribute("z")?.Value)}
    End Function

    ''' <summary>
    ''' convertit en double peu importe le symbole décimal du PC et du texte
    ''' </summary>
    ''' <param name="Texte"></param>
    ''' <returns>Si ca ne marche pas retourne Not A Number</returns>
    Private Shared Function ToDouble(ByVal Texte As String) As Double
        Dim res As Double

        If Double.TryParse(Texte.Replace(","c, "."c), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, res) Then
            Return res
        Else
            Return Double.NaN
        End If
    End Function
End Class

Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
Et 2eme boulette, c'était pas des tableaux du coup, puisqu'un tableau se déclare ainsi
Public Property test As String()
Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Bon j'ai crée toutes mes class comme ceci :
Class Presets
    Public Property Name As Integer
    Public Property SpecialUse As String
    Public Property Channels As List(Of Channels)
End Class

Class Channels
    Public Property PresetValue As List(Of PresetValue)
End Class

Class PresetValue
    Public Property Value As Double
    Public Property Embeded As List(Of Embeded) ' quand il y a le noeud HANDLE c'est qu'il y a une preset embeded
    Public Property Channel As List(Of Channel)
End Class

Class Embeded
    Public Property Name As Integer
    Public Property Numero As List(Of Numero)
End Class

Class Channel
    Public Property Fixture_id As Integer
    Public Property Attribute_Name As String
End Class

Class Numero
    Public Property Num1 As Integer
    Public Property Num2 As Integer
    Public Property Num3 As Integer
End Class


j'ai mis ces lignes pour déssirialiser une partie des données pour voir si ça marche:
 MesPresets = (
            From f In xDoc.Descendants("Preset")
            Select New Presets With
             {
                .Name = f.Attribute("name")?.Value,
                .SpecialUse = f.Attribute("SpecialUse")?.Value,
                .Channels = (From s In f.Descendants("channels")
                             Select New Channels With
                    {
                                 .PresetValue = (From t In s.Descendants("PresetValue")
                                                 Select New Channel With
              {
                                                     .Fixture_id = t.Element("channel").Attribute("Fixture_Id")?.Value,
                                                     .Attribute_Name = t.Element("Channel").Attribute("Attribute_Name")?.Value
             ))}).ToList()}).ToList()}).Tolist()

Mais Visual studio me dit qu'il manque des parenthèses fermantes mais je ne vois pas où. As tu une idée?

J'ai une autre question : est ce que ça ne pose pas de problème qu'une Property d'une class ai le même nom qu'une classe?
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Bonsoir
pour plus de lisibilité et d'efficacité de codage / déboggage, je te conseille d'aérer et de bien indenter ton code
        Dim MesPresets As List(Of Presets) =
            ('la parenthèse fermante associée est au même niveau
            From f In xDoc.Descendants("Preset")
            Select New Presets With
                 {'idem pour cette accolade
                    .Name = f.Attribute("name")?.Value,
                    .SpecialUse = f.Attribute("SpecialUse")?.Value,
                    .Channels = (From s In f.Descendants("channels")
                                 Select New Channels With
                                     {
                                         .PresetValue = (From t In s.Descendants("PresetValue")
                                                         Select New Channel With
                                                             {
                                                                 .Fixture_id = t.Element("channel").Attribute("Fixture_Id")?.Value,
                                                                 .Attribute_Name = t.Element("Channel").Attribute("Attribute_Name")?.Value
                                                             }
                                                         ).ToList()
                                     }
                                 ).Tolist()
                 }
            ).ToList()

Cela permet de bien visualiser où chaque block commence et finit.

Mais c'est pas tout.

Dans Preset, Name est un integer, or tu veux lui assigner une string.
Dans Chanels, PresetValue est une liste de PresetValue, or tu veux lui affecter une liste de Channel.

Comme je ne sais ce qui est bon (les classes ou la requête), je te laisse corriger.

J'ai une autre question : est ce que ça ne pose pas de problème qu'une Property d'une class ai le même nom qu'une classe?

Non.

Par contre, toujours dans l'idée de s'y retrouver facilement, n'appelle pas une collection de "Bidule", "Bidule", appelle la "LesBidules", ou encore "Bidules", bref au moins un pluriel qui montre qu'il y a plusieurs "Bidule"

Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Bonjour (j'avais oublié la politesse),
J'ai suivi tes conseils et modifié les noms des class. J'ai aussi modifié et ajouté des class pour mieux correspondre à mes besoins. Les voici :
Class PresetPools
    Public Property Presets As Les_Presets
    Public Property Index As Integer
End Class

Class Les_Presets
    Public Property Index As Integer
    Public Property Name As String
    Public Property SpecialUse As String
    Public Property Channels As List(Of Les_Channels)
End Class

Class Les_Channels
    Public Property PresetValue As List(Of Les_PresetValue)
End Class

Class Les_PresetValue
    Public Property Value As Double
    Public Property Embeded As List(Of Les_Embeded) ' quand il y a le noeud HANDLE c'est qu'il y a une preset embeded
    Public Property Channel As List(Of Les_Channel)
End Class

Class Les_Embeded
    Public Property Name As String
    Public Property Numero As List(Of Les_Numero)
End Class

Class Les_Channel
    Public Property Fixture_id As Integer
    Public Property Attribute_Name As String
End Class

Class Les_Numero
    Public Property Num1 As Integer
    Public Property Num2 As Integer
    Public Property Num3 As Integer
End Class

J'ai donc corrigé le code en conséquence mais j'ai deux soucis que je n'arrive pas à régler.
Voici le code:

            Dim MesPresetPool2 As List(Of PresetPools) =
            ('la parenthèse fermante associée est au même niveau
            From k In xDoc.Descendants("PresetPools")
            Select New PresetPools With
                {
                .Index = k.Attribute("index")?.Value,
                .Presets = (From l In k.Descendants("PresetPool")
                            Select New Les_Presets With
                                    {
                                    .Index = l.Attribute("index")?.Value,
                                    .Name = l.Attribute("name")?.Value,
                                    .SpecialUse = l.Attribute("SpecialUse")?.Value,
                                    .Channels = (From m In l.Descendants("Channels")
                                                 Select New Les_Channels With
                                                         {
                                                         .PresetValue = (From n In m.Descendants("PresetValue")
                                                                         Select New Les_PresetValue With
                                                                                 {
                                                                                 .Value = n.Attribute("Value")?.Value,
                                                                                 .Embeded = (From p In n.Descendants("Handle")
                                                                                             Select New Les_Embeded With
                                                                                                     {
                                                                                                     .Name = p.Attribute("name")?.Value,
                                                                                                     .Numero = (From q In p.Descendants("No")
                                                                                                                Select New Les_Numero With
                                                                                                                        {
                                                                                                                        .Num1 = q.Element("No")?.Value' A MODIFIER POUR LES NUM DES PRESETS EMBEDED
                                                                                                                        }
                                                                                                                ).ToList(),
                                                                                                      }
                                                                                            ).tolist(),
                                                                                 .Channel = (From t In n.Descendants("Channel")
                                                                                             Select New Les_Channel With
                                                                                                         {
                                                                                                            .Fixture_id = t.Element("channel").Attribute("Fixture_Id")?.Value,
                                                                                                            .Attribute_Name = t.Element("Channel").Attribute("Attribute_Name")?.Value
                                                                                                         }
                                                                                             ).ToList()
                                                                                  }
                                                                         ).tolist()
                                                          }
                                                 ).tolist()
                                    }
                            ).tolist()
                }
            ).tolist()

Avec ces erreurs:

On verra aprés mais il y aura la particularité du noeud Handle avec plusieurs éléments avec le même nom.
je me disais qu'on pourrait continuer à communiquer par mail, mais on aurait plus les balises de code. Quand penses tu?
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
J'ai suivi tes conseils et modifié les noms des class

Public Property Channel As List(Of Les_Channel)

J'ai du mal m'exprimer, je te conseillais plutôt l'inverse
Public Property LesChannels As List(Of Channel) 'LesChanels est une liste qui contiendra des instances de Channel



Ensuite je te conseille d'activer OptionStrict, à aucun moment tu prends la peine de convertir les texte en nombre (double ou integer), du coup tu laisses VB faire ce qu'il veut. Et parfois, c'est pas ce que tu veux toi.

L'erreur "Expression attendue", vient du fait qu'à la ligne au-dessus, il y a une virgule. Cette virgule veut dire que tu vas initialiser une autre propriété.

Voici un exemple pour une Personne, qui a un Nom, un Prenom et une DateDeNaissance
Dim p as New Personne with
{
    .Nom = "Sors", 'je vais encore initier le prénom est la date, il y a une virgule
    .Prenom = "Jean",
    .DateNaissance = "01/01/2000" ' pas d'autre propriété à initier -> pas de virgule

}


Une fois cette erreur corrigée, il y a un autre problème, la propriété Presets de la classe PresetPools n'est pas une liste, et dans la requête, tu veux y mettre une liste
Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
C'est corrigé (merci). Malheureusement j'ai une exception à l’exécution :
sur :
Select New Channel With
{
 .Fixture_id = CInt(t.Element("channel").Attribute("fixture_Id")?.Value),
 .Attribute_Name = t.Element("Channel").Attribute("attribute_Name")?.Value
}


avec cette erreur:
System.NullReferenceException : 'La référence d'objet n'est pas définie à une instance d'un objet.'

System.Xml.Linq.XContainer.Element(...) retournée Nothing.

J'ai vérifié il y a bien des données pour ces éléments et j'ai mis les ? avant ".value". En revanche il n'y a pas à chaque fois le nœud Handle.
Comment puis-je lui dire si le nœud existe alors tu le prends sinon tu passes à la suite?
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
Tu as mis
Element("channel")
une fois avec « c » et une fois avec « C »
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
En faisant comme ça, tu n'es pas robuste à l'absence d'un "étage", là clairement ça plante car dans t, il n'y a pas d'élément qui s'appelle "channel" (ou "Channel," un des 2).
Pour pallier ce problème, il faut mettre un ? à chaque "étage", comme je te l'ai montré au message 19 par exemple https://codes-sources.commentcamarche.net/forum/affich-10095511-acces-aux-valeurs-dans-un-xml?full#19

Dans ce cas, s'il manque quelque chose la "ligne" retourne Nothing, cependant c'est la conversion en Integer qui va planter.

C'est pourquoi, toujours au message 19, j'avais ajouté une méthode qui se chargeait de la conversion de façon robuste (accepte, le point ou la virgule et retourne un nombre par défaut si la chaine n'est pas convertible).

Cependant, telle que je te l'ai montrée, elle n'est utilisable que dans la classe ou elle a été écrite.
Il faut en faire une extension de classe.

Je n'ai pas le temps ce matin.

Tu peux chercher sur le net ce qu'est une extension, si tu ne t'en es pas sorti je te ferais un exemple ce soir
Commenter la réponse de wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Bonjour,
C'est très sympa de m'aider : je n'y serai pas arrivé seul.

J'ai réussi à créer l'extension de class pour convertir en double.
J'ai aussi corrigé la requête pour Les_Channels : j'avais mis un .element de trop alors qu'il fallait accéder aux attributs.
En revanche, je me suis aperçu que dans mon xml pour le nœud "PresetValue" il y a soit l'attribut "value" soit l'élément "Handle", avec à chaque fois l'élément "Channel". Du coup ça lève une exception quand je lance la dessérialisation dans l'extension de class.
J'ai bien mis les points d'interrogations quand je récupère des valeurs d'attribut mais peut on les mettre aussi pour qu'il teste la présence de l'élément ?
Sinon est il possible d'inclure des conditions ?
Et sinon comment puis-je faire ?
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
PEux tu poster le code de l’extension.
Je ne suis pas encore rentré, mais j’y regarderai ce soir
Commenter la réponse de wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Le voici avec mes modifs :
Module Module_extensions

    <Extension()>
    Function Mon_todouble(ByVal texte As String) As Double
        Dim res As Double

        If texte <> Nothing Then
            If Double.TryParse(texte.Replace(",", "."), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, res) Then
                Return res
            Else
                Return Double.NaN
            End If
        End If
    End Function

End Module

J'ai enlevé 2 c qui étaient respectivement après "." et après "," dans le "texte.replace".
et j'ai rajouté une condition (pour que ça marche) mais je ne pense pas que ce soit la meilleur façon de faire.
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Si c’est bien, je n’avais pas vérifié si le tryparse accepte nothing en entrée, à priori non.

Par contre en l’état, si c’est nothing tu ne retourne rien.

Tu peux faire.

        If texte <> Nothing Then
            If Double.TryParse(texte.Replace(",", "."), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, res) Then
                Return res
            End If
        End If
        Return Double.NaN


Ou encore
        If texte <> Nothing AndAlso Double.TryParse(texte.Replace(",", "."), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, res) Then
                Return res
        End If
        Return Double.NaN


J’ai tapé de tête.


Aussi, j’avais mis double.NaN comme retour en cas d’absence de texte, mais ça peut (certainement) mettre la garouille dans de futurs calculs, il faudrait dont vérifier.

Tu peux maintenant faire une autre extension pour les Integer.
Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
Bonjour,
J'ai fait pas mal de changements dans les class et aussi dans la requête pour récupérer les valeurs. Il y a juste une chose qui ne fonctionne pas comme je voudrais.
Dans le fichier xml, il peut y avoir ce genre de chose :
<Preset index="1" name="ch4 HOME">
				<Values>
					<Channels>
						<PresetValue>
							<Handle name="warp niches 0.1">
								<No>1</No>
								<No>0</No>
								<No>1</No>
							</Handle>
							<Channel fixture_id="4" channel_id="4" attribute_name="FIXTUREGLOBALRESET" />
						</PresetValue>
						<PresetValue>
							<Handle name="warp niches 0.1">
								<No>1</No>
								<No>0</No>
								<No>1</No>
							</Handle>
							<Channel fixture_id="4" channel_id="4" attribute_name="PAN" />
						</PresetValue>
					</Channels>
				</Value>
			<Preset>

Je récupère déjà le <Handle>.name mais je voudrais avoir les 3 numéros concaténés dans la même variable. Je ne trouve pas comment faire ?
As tu une idée ?
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Tu peux utiliser une variable intermédiaire, avec le mot clé Let
        Dim texte = "<Preset index=""1"" name=""ch4 HOME"">
	<Values>
		<Channels>
			<PresetValue>
				<Handle name=""warp niches 0.1"">
					<No>1</No>
					<No>0</No>
					<No>1</No>
				</Handle>
				<Channel fixture_id=""4"" channel_id=""4"" attribute_name=""FIXTUREGLOBALRESET"" />
			</PresetValue>
			<PresetValue>
				<Handle name=""warp niches 0.1"">
					<No>3</No>
					<No>2</No>
					<No>1</No>
				</Handle>
				<Channel fixture_id=""4"" channel_id=""4"" attribute_name=""PAN"" />
			</PresetValue>
		</Channels>
	</Values>
</Preset>"

        Dim lesPresetsJoints As List(Of String) = (From h In XDocument.Parse(texte).Descendants("Handle")
                                                   Let lesPresets =
                                                       (
                                                        From p In h.Descendants("No")
                                                        Select p.Value
                                                       )
                                                   Select String.Join(";", lesPresets)
                                                   ).ToList()



Ou faire ta requête directement dans le String.Join
        Dim lesPresetsJoints As List(Of String) = (From h In XDocument.Parse(texte).Descendants("Handle")
                                                   Select String.Join(";",
                                                        From p In h.Descendants("No")
                                                        Select p.Value
                                                                      )
                                                   ).ToList()


Le résultat est le même

Commenter la réponse de Whismeril
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
En fait les données qui se trouvent dans Handle sont liés à la PresetValue donc je voudrais mettre les "No" dans chaque PresetValue correspondante.
j'ai mis ce code mais il me dit :
System.InvalidCastException : 'Impossible d'effectuer un cast d'un objet de type 'WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]' en type 'System.String'.'


Voici le code :
            MesPresetPool =
            (
            From k In xDoc.Descendants("PresetPool")
            Select New PresetPool With
                {
                .Index = Mon_ToInteger(k.Attribute("index")?.Value),
                .Les_Presets = (From l In xDoc.Descendants("Preset")
                                Select New Presets With
                                    {
                                    .Index = Mon_ToInteger(l.Attribute("index")?.Value),
                                    .Name = l.Attribute("name")?.Value,
                                    .SpecialUse = l.Attribute("SpecialUse")?.Value,
                                    .Les_values = (From m In l.Descendants("Values")
                                                   Select New Values With
                                                            {
                                                         .Les_Channels = (From v In m.Descendants("Channels")
                                                                          Select New Channels With
                                                                                {
                                                                         .Les_PresetValue = (From n In v.Descendants("PresetValue")
                                                                                             Select New PresetValue With
                                                                                                 {
                                                                                                 .Value = Mon_todouble(n.Attribute("Value")?.Value),
                                                                                                 .Embeded_Name = n?.Element("Handle")?.Attribute("name")?.Value,
                                                                                                 .Embeded_Num = (From p In n?.Descendants("Handle")
                                                                                                                 Select String.Join(";",
                                                                                                                            From u In p.Descendants("No")
                                                                                                                            Select p?.Value
                                                                                                                                    )
                                                                                                                 ),
                                                                                                 .Fixture = Mon_ToInteger(n.Element("Channel")?.Attribute("fixture_id")?.Value),
                                                                                                 .Attribute_name = n.Element("Channel")?.Attribute("attribute_name")?.Value
                                                                                                  }
                                                                                             ).ToList()
                                                                                }
                                                                        ).ToList()
                                                            }
                                                    ).ToList()
                                    }
                            ).ToList()
                }
            ).ToList()


voir de la ligne 24 a 29
P.S. J'ai modifié la propriété Embeded_Num de la class PresetValue en la déclarant comme une string.
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -

 .Embeded_Num = (From p In n?.Descendants("Handle")
              Select String.Join(";",
                       From u In p.Descendants("No")
                        Select p?.Value
                              )

qui dit from dit collection et donc c'est pas compatible d'une string.
Et en plus, tu sectionnes p.Value et pas u.Value.

Si tu es sûr et certain qu'il ne peut y avoir qu'un seul "Handle" ceci devrait fonctionner
 .Embeded_Num = (String.Join(";",
                       From u In n?.Descendants("No")
                        Select u?.Value
                              )
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
Aussi, tu as fait de Mon_ToInteger une extension.
L'interêt d'une extension est d'ajouter une méthode à un type.

L'idée étant de s'en servir comme ceci
.Index = l.Attribute("index")?.Value.Mon_ToInteger(),
Commenter la réponse de wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
0
Merci
C'est bon ! Oui il ne peut y avoir qu'un seul Handle.

Je ne sais pas si tu as remarqué mais ces No correspondent aux PresetPools ; PresetPool ; Preset.
C'est à dire que dans notre exemple :
la preset avec l'index 5 a les valeurs de la preset 1dans le PresetPool 4.
donc la valeur 32.499603 pour l'attribute_name "COLORRGB1" du fixture_id 10

dit rapidement:
(Dans une preset j'ai un lien vers une autre preset mais je voudrais la valeur au lieu du lien)

Je sais pas si c'est très clair mais comment puis je aller chercher ces valeurs pour les mettre dans MesPresetPool

N'hésite pas à me demander des précisions.
Commenter la réponse de wholehog2
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Quand tu dis
dans notre exemple :
C’est dans le fichier complet?
wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
-
Oui c'est sur le fichier complet.
Est ce su'on peut le faire dans la requête ou est ce qu'il faut le faire après ?
wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
-
Tu n'as pas d'idée ?
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
Je n’ai pas eu le temps d’essayer, mais à priori je pense qu’il faut le faire en 2 passes
wholehog2
Messages postés
58
Date d'inscription
lundi 25 juin 2007
Statut
Membre
Dernière intervention
17 mai 2019
-
Ok pas de souci.
Est ce qu'il est possible de faire une requête du style select "preset" where "handle" existe sur un xml pour avoir toutes les presets qui on un élément "handle"?
Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312 -
Oui
Commenter la réponse de Whismeril
Messages postés
13844
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
21 octobre 2019
312
0
Merci
Je n'ai pas compris ton exemple,

la preset avec l'index 5 a les valeurs de la preset 1dans le PresetPool 4.
donc la valeur 32.499603 pour l'attribute_name "COLORRGB1" du fixture_id 10


Dans le fichier complet, des preset avec l'index 5, y'en a plein, je sais pas de laquelle tu parles.
La preset 1 dans le PresetPool 4 contient effectivement (entre autre) COLORRGB1, mais pas 32.499603 ni fixture_id


Commenter la réponse de Whismeril