2009-07-31 10 views
5

Je lutte désérialiser le XML suivant:alphabétisé LINQ to XML: Les meilleures pratiques pour désérialiser attribut/valeur à paires variable/valeur structurés

<?xml version="1.0" encoding="utf-8" ?> 

<conf name="settings"> 

    <item name="lorem" 
     one="the" 
     two="quick" 
     three="brown" 
     four="fox" 
     five="jumps" 
     six="over" 
     seven="the" 
     eight="lazy" 
     nine="dog" 
      /> 

    <item name="ipsum" 
     one="how" 
     two="many" 
     three="roads" 
     four="must" 
     five="a" 
     six="man" 
     seven="walk" 
     eight="down" 
     nine="?" 
      /> 

</conf> 

espérant le faire dans la plus élégante et succincte en utilisant LINQ-to-XML, mais étant donné que je ne suis pas le plus intelligent de la ville en ce qui concerne les méthodes imbriquées, les types dédiés, les génériques, et cétera, j'ai pensé que ce serait une bonne idée de demander les gars aimeraient aller de l'avant et me montrer un peu d'alphabétisation LINQ :)

Maintenant pour chaque valeur que je fais quelque chose comme:

XDocument config = XDocument.Load("whatever.conf"); 

var one = from q in config.Descendants("item") 
      select (string)q.Attribute("one"); 

var two = from q in config.Descendants("item") 
      select (string)q.Attribute("two"); 

Et Je ne sais je suis tout à fait manquer le point, non seulement parce que je me répète beaucoup là-bas, mais aussi parce que les requêtes travail seulement quand il n'y a qu'un seul élément donc, encore une fois si vous avez des commentaires ou suggestion, ce serait vraiment apprécié. Merci beaucoup d'avance!

MISE À JOUR: en cas que peut-être l'exemple précédent était pas vraiment utile, voici un plus genre de scénario réaliste:

<?xml version="1.0" encoding="utf-8" ?> 

<conf name="ftp-settings" freq="daily" time="23:00"> 
    <item name="isis" 
      host="10.10.1.250" 
      user="jdoe" 
      pass="4/cB0kdFGprXR/3oTs8mtw==" 
      file="backup.tar.gz" 
      path="/var/log" 
     /> 
    <item name="seth" 
      host="10.10.2.250" 
      user="jdoe" 
      pass="4/cB0kdFGprXR/3oTs8mtw==" 
      file="backup.tar.gz" 
      path="/var/log" 
     /> 
</conf> 

Par conséquent, pour chacun de ces articles que je voudrais générer des variables afin Je peux les passer en paramètres pour une méthode de gestion de FTP.

SOLVED:

Il est aussi facile que de faire une foreach:

var elements = from element in xml.Descendants("item") select element; 

foreach (XElement item in elements) { 
    ftp.DownloadFile(
     item.Attribute("host").Value, 
     item.Attribute("user").Value, 
     item.Attribute("pass").Value, 
     item.Attribute("file").Value, 
     item.Attribute("path").Value 
     ); 
} 

Répondre

3

Normalement, je vous attendriez à vouloir une seule représentation de chaque élément, au lieu d'une séquence de " un "valeurs et une autre séquence de" deux "valeurs. En d'autres termes, j'attends quelque chose comme:

var items = config.Descendants("item") 
        .Select(element => Item.FromXElement(element)); 

Si vous avez beaucoup d'attributs dans un seul élément, je trouve utile de séparer le code « faire un objet de cet élément » dans son propre méthode (dans ce cas Item.FromXElement) plutôt que de tout bourrer dans la requête. Si Item ne devrait pas connaître son LINQ à la représentation XML, mettre quelque part la méthode qui devrait :)

items est alors un IEnumerable<Item> que vous pouvez convertir en une liste ou tout ce que vous voulez faire.

Bien sûr, cela dépend vraiment de ce que vous essayez de faire - et nous ne savons pas vraiment ce que cela est censé représenter. Peut-être vous vraiment faire voulez que chaque « séquence d'attributs » séparément ...


Item.FromXElement ressemblerait à quelque chose comme:

public static Item FromXElement(XElement element) 
{ 
    string name = (string) element.Attribute("name"); 
    string host = (string) element.Attribute("host"); 
    // etc 
    return new Item(name, host, ...); 
} 

(Où est évident que vous créez un constructeur auriez avec les paramètres appropriés.)

+0

tous premiers merci beaucoup pour votre commentaire Jon! J'ai vraiment besoin de les garder séparés; Imaginez que je persiste, disons, des détails de connexion ou des signets, etc., alors il faut séparer les éléments * lorem * et * ipsum *, puis créer des paires clé/valeur à partir de ses attributs. J'espère que vous avez suivi mon élaboration, de toute façon n'hésitez pas à me demander d'autres efforts explicatifs :) –

+1

Je ne suis pas * vraiment * l'élaboration, non. Pourriez-vous éditer votre question pour donner un exemple plus complet de ce que vous essayez de faire et comment vous voulez utiliser l'information par la suite? –

+0

Je l'ai fait. Merci beaucoup d'avance Jon. –

1

je ferais ceci:

XDocument config = XDocument.Load("whatever.conf"); 

var pairs = from q in config.Descendants("item") 
      select new { 
       One = (string)q.Attribute("one"), 
       Two = (string)q.Attribute("two") }; 

var ones = pairs.Select(pair => pair.One); 
var twos = pairs.Select(pair => pair.Two); 
+0

Pavel remercie beaucoup pour le commentaire, bien que ce dont j'ai vraiment besoin est d'avoir deux collections résultantes isis et seth, toutes les deux avec tous ses attributs accessibles peut-être sous la forme de isis.host, isis.user, etc. –

Questions connexes