Skocz do zawartości

Linq to XML


baton

Recommended Posts

Witam,
mam takiego xml'a jak poniżej. Próbuje napisać zapytanie dzięki któremu mógłbym uzyskać takiego outputa:
12 10 11 5 01 1 AN 0454741
10 05 06 2 00 1 SW 0729103
26 05 04 2 01 1 G 0264443

Próbowałem zrobić to tak:
 

var xml = XDocument.Load(@"test.xml");

            var query = from c in xml.Descendants()
                // where (string)c.Attribute("name") == "WOJ"
                select new
                {
                    name1 = ((string)c.Attribute("name") == "name1")? c.Value : string.Empty,
                    name2 = ((string)c.Attribute("name") == "name2") ? c.Value : string.Empty,
                    name3 = ((string)c.Attribute("name") == "name3") ? c.Value : string.Empty
...
                };

            foreach (var item in query)
            {
                Console.WriteLine(item.name1 + " " + item.name2 + " " + item.name3 ...);
            }



ale nie działa:/ Moglibyście pomóc?
 

<?xml version="1.0" encoding="UTF-8"?>
<root>
<catalog name="test" type="all" date="2016-01-01">
<row>
<col name="name1">12</col>
<col name="name2">10</col>
<col name="name3">11</col>
<col name="name4">5</col>
<col name="name5">01</col>
<col name="name6">1</col>
<col name="name7">AN</col>
<col name="name8">0454741</col>
<col name="name9">0454741</col>
<col name="name10">2016-01-01</col>
</row>
<row>
<col name="name1">10</col>
<col name="name2">05</col>
<col name="name3">06</col>
<col name="name4">2</col>
<col name="name5">00</col>
<col name="name6">1</col>
<col name="name7">SW</col>
<col name="name8">0729103</col>
<col name="name9">0729095</col>
<col name="name10">2016-01-01</col>
</row>
<row>
<col name="name1">26</col>
<col name="name2">05</col>
<col name="name3">04</col>
<col name="name4">2</col>
<col name="name5">01</col>
<col name="name6">1</col>
<col name="name7">G</col>
<col name="name8">0264443</col>
<col name="name9">0264443</col>
<col name="name10">2016-01-01</col>
</row>
</catalog>
</root> 



 

Link do komentarza
Udostępnij na innych stronach

Wydaje mi się, że iterowanie po wszystkich węzłach i wyciąganie danych tylko z tych węzłów, które nas interesują nie jest najlepszym pomysłem. Lepiej wyciągnąć tylko węzły znaczące, np. najpierw stworzyć kolekcję węzłów row i następnie z nich wyciągać te węzły col które mają dla zadanego atrybutu konkretne wartości - np. wszystkie col które w wartości atrybutu name zawierają ciąg 'name'. Można to zrobić takim np. zapytaniem (wyświetli wyciągnięte dane oddzielone spacją):

List<string> rowsDetails =
                xml.Descendants()
                   .Where(x => x.Name == "row")
                   .Select(row =>
                        string.Join(" ", row.Descendants()
                                            .Where(x => x.Name == "col" && ((string)x.Attribute("name")).Contains("name"))
                                            .Select(y => y.Value)
                        )
                    ).ToList();

rowsDetails.ForEach(Console.WriteLine);

Oczywiście jeżeli zamierzamy robić coś więcej z danymi z XMLa to zamiast List<string> należy użyć listy obiektów prezentujących dane z każdego wiersza - np List<RowDetail> i wówczas można to zrobić tak:

public class RowDetails
{
  public string Name1 { get; set; }
  public string Name2 { get; set; }
  public string Name3 { get; set; }
  ...
}
...
List<RowDetails> rowsDetails = xml.Descendants().Where(x => x.Name == "row").Select(row =>
{
  var desc = row.Descendants().Where(x => x.Name == "col");
  var xElements = desc as List<XElement> ?? desc.ToList();

  var n1 = xElements.FirstOrDefault(x => (string)x.Attribute("name") == "name1")?.Value;
  var n2 = xElements.FirstOrDefault(x => (string)x.Attribute("name") == "name2")?.Value;
  var n3 = xElements.FirstOrDefault(x => (string)x.Attribute("name") == "name3")?.Value;
  ...
    
  return new RowDetails()
  {
  	Name1 = n1,
  	Name2 = n2,
  	Name3 = n3
    ...
  };
}).ToList();

 

Link do komentarza
Udostępnij na innych stronach

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...