2010-12-30 18 views
15

Mam trzy listy w C#, nazwy zmiennych są l_lstData1, l_lstData2, l_lstData3.LINQ and XDocument: Jak utworzyć plik XML?

struktura plików jest

<FileDetails> 
    <Date FileModified="29/04/2010 12:34:02" /> 
    <Data Name="Data_1" DataList="India" Level="2" /> 
    <Data Name="Data_2" DataList="chennai" Level="2" /> 
    <Data Name="Data_3" DataList="hyderabad" Level="2" /> 
    <Data Name="Data_4" DataList="calcutta" Level="2" /> 
    <Data Name="Data_5" DataList="vijayawada" Level="1" /> 
    <Data Name="Data_6" DataList="cochin" Level="1" /> 
    <Data Name="Data_7" DataList="madurai" Level="0" /> 
    <Data Name="Data_8" DataList="trichy" Level="0" /> 
</FileDetails> 

Wartości 3 wymienia się w następujący sposób:

l_lstData1[0] = "India"; 
l_lstData1[1] = "chennai"; 
l_lstData1[2] = "hyderabad"; 
l_lstData1[3] = "calcutta"; 

więc cechą poziom powyżej XML (elementów: Dane) ma wartość = "2".

l_lstData2[0] = "vijayawada"; 
l_lstData2[1] = "cochin";  

więc atrybut poziomu powyższego XML (element: Data) ma wartość = "1".

l_lstData3[0] = "madurai"; 
l_lstData3[1] = "trichy";  

więc atrybut poziomu powyższego XML (element: Data) ma wartość = "0".

Odpowiedz

30

Nie jest jasne dokładnie dlaczego „poziom” atrybuty są określone, ale to spowodowałoby istotne XML dla Ciebie:

// Used for side-effects in the XElement constructor. This is a bit icky. It's 
// not clear what the "Name" part is really for... 
int count = 1; 

var doc = new XDocument(
    new XElement("FileDetails", 
     new XElement("Date", new XAttribute("FileModified", DateTime.UtcNow)), 
     l_lstData1.Select(x => new XElement("Data", 
      new XAttribute("Name", "Data_" + count++), 
      new XAttribute("DataList", x), 
      new XAttribute("Level", 2))), 
     l_lstData2.Select(x => new XElement("Data", 
      new XAttribute("Name", "Data_" + count++), 
      new XAttribute("DataList", x), 
      new XAttribute("Level", 1))), 
     l_lstData3.Select(x => new XElement("Data", 
      new XAttribute("Name", "Data_" + count++), 
      new XAttribute("DataList", x), 
      new XAttribute("Level", 0))))); 

Prawdopodobnie byłoby neater jeśli można wyodrębnić projekcje od a element listy do jego elementu, ale bit "Data_" + count sprawia, że ​​jest to trudne. Nie jest jasne, dlaczego potrzebujesz czegoś takiego, aby być szczerym ... gdybyś mógł odejść bez tego, kod mógł być czystszy.

Przypuszczam, że alternatywą byłoby stworzenie dokumentu bez atrybutówName, a następnie wypełnienie ich. Na przykład:

private static IEnumerable<XElement> ProjectList(IEnumerable<string> list, 
    int level) 
{ 
    return list.Select(x => new XElement("Data", 
     new XAttribute("DataList", x), 
     new XAttribute("Level", level))); 
} 

następnie:

var doc = new XDocument(
    new XElement("FileDetails", 
     new XElement("Date", new XAttribute("FileModified", DateTime.UtcNow)), 
     ProjectList(l_lstData1, 2), 
     ProjectList(l_lstData2, 1), 
     ProjectList(l_lstData3, 0))); 

int count = 1; 
foreach (var element in doc.Descendants("Data")) 
{ 
    element.SetAttributeValue("Name", "Data_" + count++); 
} 
2

Co o:

XDocument doc = new XDocument(); 

var total = (from a in list1 select new { Name = a, Level = 2 }).Concat(
      from b in list2 select new { Name = b, Level = 1 }).Concat(
      from c in list3 select new { Name = c, Level = 0 }); 

XElement root = new XElement("FileDetails", from i in Enumerable.Range(0, total.Count()) 
              let element = total.ElementAt(i) 
              let name = new XAttribute("Name", String.Format("Data_{0}", i + 1)) 
              let level = new XAttribute("Level", element.Level) 
              let datalist = new XAttribute("DataList", element.Name) 
              select new XElement("Data", name, datalist, level), 
              new XElement("Date", new XAttribute("FileModified", DateTime.Now)));