2014-03-26 40 views
0

我有一個XML像下面以根爲鐵路LINQ查詢來解析給出複雜的XML

 <rail> 
     <timetable> 
     <trainParts> 
       <trainPart id="tp_1" name="1" timetablePeriodRef="ttp_2012_13" categoryRef="cat_Commuter" processStatus="planned" trainNumber="1"> 
       <operatingPeriodRef ref="Daily" /> 
       <ocpsTT> 
        <ocpTT ocpType="begin" ocpRef="ocp_SWH"> 
        <sectionTT trackInfo="SWH-DM" /> 
        </ocpTT> 
        <ocpTT ocpType="stop" ocpRef="ocp_SE"> 
        <times arrival="16:16:00" departure="16:18:00" scope="scheduled" /> 
        <sectionTT trackInfo="SE-DM" /> 
        </ocpTT> 
    . 
    . 
    . 
    so on 
</ocpsTT> 
     </trainPart> 
     </trainParts> 
     </timetable> 
     </rail> 

現在這個樣子有很多車次,其細節我有一個去解析。 我可以一次使用linq解析一個孩子及其屬性,但我想解析所有孩子及其元素。 說的trainNumer =「1」我需要得到

categoryRef 
    processStatus 

    operatingPeriodRef 

    ocpType 
    ocpRef 
    trackInfo 

    arrival 
    departure 

注:在某些情況下,時間標記包含出發的到來是不是有

我曾嘗試寫的代碼如下:

public void trainDetails(string trainNumber) 
      { 

       var xdoc = XDocument.Load("Rail.xml"); 
       XNamespace ad = "http://www.rail.org/schemas/2009"; 
       var train = (from t in xdoc.Root.Elements(ad + "timetable") 
         let d = t.Element(ad + "trainParts").Element("trainPart") 
         where (string)t.Attribute("number") == trainNumber 
         select new 
         { 
          operatingPeriod=(from s1 in d.Elements(ad+"operatingPeriodRef") 
               operatingref=(string)s1.Attribute("ref") 
               }).ToList() 
          } 
         select new 
         { 
          trainOcpsTT= (from s2 in d.Elements(ad + "ocpsTT").Elements(ad+"ocpTT") 
              select new 
              { 
               ocpType=(string)s2.Attribute("ocpType"), 
               ocpRef=(string)s2.Attribute("ocpRef") 
               }).ToList() 
          }).FirstOrDefault(); 

     } 
      } 

我無法框架查詢正確.. 是否有可能在一個XML LINQ查詢本身得到所有這些? 如果沒有,那麼這就是在這種情況下,正確的方法..

回答

1

這裏是我的建議:

public class TrainInfo 
{ 
    public string categoryRef { get; set; } 
    public int trainNumber { get; set; } 
    public string processStatus { get; set; } 
    public string operatingPeriodRef { get; set; } 
    public List<ocpsTTs> ocpsTT { get; set; } 
} 

public struct ocpsTTs 
{ 
    public string ocpType; 
    public string ocpRef; 
    public string arrival; 
    public string departure; 
    public string scope; 
    public string trackInfo; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     TrainInfo ti = ProcessXml(@"XMLFile1.xml", 1); 
    } 

    static TrainInfo ProcessXml(string xmlfile, int trainnumber) 
    { 
     TrainInfo retVal; 

     try 
     { 
      XmlDocument xmlDoc = new XmlDocument(); 
      xmlDoc.Load(xmlfile); 

      XNamespace xns = "http://www.rail.org/schemas/2009"; 
      XDocument xdoc = System.Xml.Linq.XDocument.Parse(xmlDoc.InnerXml); 

      retVal = 
       (from c 
       in xdoc.Root.Elements(xns + "timetable").Elements(xns + "trainParts").Elements(xns + "trainPart") 
       where c.Attribute("trainNumber").Value.Equals(trainnumber.ToString()) 
       select new TrainInfo 
       { 
        categoryRef = c.Attribute("categoryRef").Value, 
        trainNumber = Int32.Parse(c.Attribute("trainNumber").Value), 
        processStatus = c.Attribute("processStatus").Value, 
        operatingPeriodRef = c.Element(xns + "operatingPeriodRef").Attribute("ref").Value, 
        ocpsTT = (from tt in c.Elements(xns + "ocpsTT").Descendants(xns + "ocpTT") 
           let timeinfo = tt.Elements(xns + "times").Any() 
           select new ocpsTTs 
           { 
            ocpType = tt.Attribute("ocpType").Value, 
            ocpRef = tt.Attribute("ocpRef").Value, 
            arrival = timeinfo ? tt.Element(xns + "times").Attribute("arrival").Value : string.Empty, 
            departure = timeinfo ? tt.Element(xns + "times").Attribute("departure").Value : string.Empty, 
            scope = timeinfo ? tt.Element(xns + "times").Attribute("scope").Value : string.Empty, 
            trackInfo = tt.Element(xns + "sectionTT").Attribute("trackInfo").Value, 
           }).ToList() 
       }).FirstOrDefault(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      retVal = null; 
     } 

     return retVal; 
    } 
} 
+0

由於它是完美的尤其是當我從來不喜歡使用結構,但它是真正的好辦法.. – Silver

+0

但是這段代碼只解析單個數字的列車號碼,而不是兩個數字或3個或更多的數字列車號碼 – Silver

+0

當時沒有看到您的反對意見,無論如何,我已經測試了一個3位數的號碼,並且適合我。 – JPG