2013-06-03 16 views
12

Jestem nowy zarówno dla XML, jak i C#; Próbuję znaleźć sposób wydajnego analizowania danego pliku xml w celu pobrania odpowiednich wartości liczbowych, w oparciu o wartość "proj_title" = heat_run lub dowolne inne możliwe wartości. Na przykład, obliczając czas trwania określonego testu (proj_end val-proj_start val).Parsowanie pliku XML przy użyciu C#?

ex.xml: 

<proj ID="2"> 
     <proj_title>heat_run</proj_title> 
     <proj_start>100</proj_start> 
     <proj_end>200</proj_end> 
</proj> 

... Nie można wyszukiwać według proj ID ponieważ wartość ta nie jest stała od testu do testowania bieg. Powyższy plik jest ogromny: ~ 8mb, i jest ~ 2000 tagów w/nazwa proj_title. czy istnieje skuteczny sposób, aby najpierw znaleźć wszystkie nazwy znaczników w/proj_title = "heat_run", a następnie pobrać wartość początkową i końcową proj dla tego konkretnego proj_title przy użyciu C# ??

Oto mój aktualny kod C#:

public class parser 
{ 
    public static void Main() 
    { 
     XmlDocument xmlDoc= new XmlDocument(); 
     xmlDoc.Load("ex.xml"); 

     //~2000 tags w/ proj_title 
     //any more efficient way to just look for proj_title="heat_run" specifically? 
     XmlNodeList heat_run_nodes=xmlDoc.GetElementsByTagName("proj_title"); 
    } 
}  
+0

miałem dużo szczęścia z wykorzystaniem serializacji XML, gdzie można włączyć XML do obiektów ... [ten link] (http://support.microsoft.com/kb/815813) może ci pomóc –

Odpowiedz

3

Zastosowanie XDocument i użyć API LINQ. http://msdn.microsoft.com/en-us/library/bb387098.aspx

Jeśli wydajność nie jest taka, jakiej oczekujesz po wypróbowaniu, musisz poszukać parsera sax. Analizator składniowy Sax nie załaduje całego dokumentu do pamięci i spróbuje zastosować wyrażenie Xpath do wszystkich elementów w pamięci. Działa bardziej w przypadku podejścia opartego na zdarzeniach, aw niektórych przypadkach może być znacznie szybszy i nie zużywa tyle pamięci.

Prawdopodobnie istnieją parsery sax dla .NET, nie użyłem ich sam dla .NET, ale zrobiłem to dla C++.

14

8MB naprawdę nie jest bardzo duży według nowoczesnych standardów. Osobiście używam LINQ do XML:

XDocument doc = XDocument.Load("ex.xml"); 
var projects = doc.Descendants("proj_title") 
        .Where(x => (string) x == "heat_run") 
        .Select(x => x.Parent) // Just for simplicity 
        .Select(x => new { 
           Start = (int) x.Element("proj_start"), 
           End = (int) x.Element("proj_end") 
          }); 

foreach (var project in projects) 
{ 
    Console.WriteLine("Start: {0}; End: {1}", project.Start, project.End); 
} 

(oczywiście dostosować to do własnych potrzeb - to naprawdę nie jest jasne, co trzeba zrobić w oparciu o pytaniu.)

zapytania Alternatywa:

var projects = doc.Descendants("proj") 
        .Where(x => (string) x.Element("proj_title") == "heat_run") 
        .Select(x => new { 
           Start = (int) x.Element("proj_start"), 
           End = (int) x.Element("proj_end") 
          }); 
+0

To bardzo mi pomogło! Po prostu muszę dodać 1 dodatkowy warunek Where. Czy istnieje opcja w LINQ/C#, która na przykład odnosi się do przodka x? jak Where (x => (string) x == "heat_run" && (string) x.Ancestor == "heat_test"). Próbowałem tego i nie zadziałało? – jerryh91

+0

@ jerryh91: Cóż, możesz użyć 'Parent', ale zazwyczaj pracuję na odwrót - znajdź rodzica z określonym dzieckiem. –