2009-07-31 8 views
5

mam zapasy deserializacji następujące XML:Literate LINQ-to-XML: Najlepsze praktyki do deserializowania atrybut/wartość strukturyzowanych par zmienna/wartość

<?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> 

nadzieję zrobić w najbardziej elegancki i zwięzły sposób użycia LINQ-do-XML, ale biorąc pod uwagę, że nie jestem najmądrzejszym dzieckiem w mieście, jeśli chodzi o metody zagnieżdżone, typy wnioskowane, generyczne, et cétera, pomyślałem, że byłoby dobrym pomysłem zapytać, czy któryś z was faceci chcieliby pokazać mi trochę alfabetu LINQ :)

W tej chwili dla każdej wartości robię coś takiego:

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"); 

I wiem jestem całkowicie brakuje punktu, nie tylko dlatego, że ja powtarzam wiele tam, ale także dlatego, że pyta tylko pracę, gdy istnieje tylko jeden element tak, znowu, jeśli masz jakiś komentarz lub sugestia, że ​​byłoby to naprawdę docenione. Z góry dziękuję!

UPDATE: w przypadku, że być może nie były przykładem była bardzo pomocna, tutaj jest bardziej rodzaj realistycznego scenariusza:

<?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> 

Dlatego dla każdej z tych pozycji chciałbym generować zmienne tak Mogę przekazać je jako parametry dla niektórych metod zarządzania FTP.

rozwiązany:

To było tak proste, jak robi 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 
     ); 
} 

Odpowiedz

3

Normalnie bym oczekiwać chce pojedynczą reprezentację każdego elementu, zamiast jednej sekwencji " jedną "wartości i kolejną sekwencję" dwóch "wartości. Innymi słowy, chciałbym się spodziewać czegoś podobnego:

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

Jeśli masz wiele atrybutów w jednym elemencie, uważam, że warto wydzielić „make obiekt z tego elementu” kodu na własną rękę metoda (w tym przypadku Item.FromXElement) zamiast umieszczać ją w zapytaniu. Jeśli Item nie powinien wiedzieć o swoim LINQ do reprezentacji XML, umieścić gdzieś metody, które powinny :)

items jest wtedy IEnumerable<Item> które można przekształcić w listy lub cokolwiek innego, co chcesz zrobić.

Oczywiście to naprawdę zależy od tego, co próbujesz zrobić - i tak naprawdę nie wiemy, co to ma reprezentować. Może naprawdę zrobić aby każdy „sekwencja atrybut” osobno ...


Item.FromXElement będzie wyglądać następująco:

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

(gdzie oczywiście chcesz utworzyć konstruktor z odpowiednimi parametrami.)

+0

pierwszy all Bardzo dziękuję za komentarz Jon! Naprawdę muszę zachować te oddzielne; Wyobraź sobie, że utrzymuję się, powiedzmy, szczegóły połączenia lub zakładki, i tak dalej, to naprawdę zależy na oddzieleniu elementów * lorem * i * ipsum *, a następnie na tworzeniu par klucz/wartość poza ich atrybutami. Mam nadzieję, że śledziłeś moje opracowanie, w każdym razie nie wahaj się poprosić mnie o dalsze wyjaśnienia :) –

+1

Nie * tak * podążam za opracowaniem, nie. Czy możesz edytować swoje pytanie, aby podać pełniejszy przykład tego, co próbujesz zrobić i jak chcesz później wykorzystać te informacje? –

+0

Zrobiłem. Z góry dziękuję z góry Jon. –

1

chciałbym to zrobić:

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 bardzo dziękuje za komentarz, chociaż to, czego naprawdę potrzebuję, to mieć dwie wynikowe kolekcje isis i seth, obie z wszystkimi dostępnymi atrybutami dostępnymi być może w postaci isis.host, isis.user, i tak dalej. –