2013-03-26 62 views
0

我正在試圖製作一個應用程序,顯示包括公交車號碼,Aimed小時和預計時間在內的bush application。如果在LINQ中聲明(如果沒有值做某事......)

我從HttpWebRequest得到我的(活的)信息。我的請求響應以XML格式存儲在字符串變量中。

我可以得到所有我想要的信息;如公交小時,Aimed小時和預計小時。

問題是,如果沒有預期的小時,將不會顯示任何內容。我喜歡在沒有預期的時間我的代碼只是需要相同的值針對時間:

一個例子

Bus | Aimed | Execepted 
----------------------- 
1 | 17:05 | 17:07 
2 | 17:05 | <nothing> so take value of aimed -> 17:05 

我已經下面的代碼

//XMLResponse put in documentRoot 
//responseFromServer is a string variable in XML format with all the information 
XElement documentRoot = XDocument.Parse(responseFromServer).Root; 
XNamespace ns = "http://www.siri.org.uk/"; 

var buses = (from tblBuses in documentRoot.Descendants(ns + "PublishedLineName") 
      select tblBuses.Value).ToList(); 
var expHours = (from tblHours in documentRoot.Descendants(ns + "ExpectedDepartureTime") 
       select tblHours.Value).ToList(); 

foreach (var bus in buses) 
{ 
    string output = bus.Substring(bus.IndexOf('T') + 1); 
    int index = output.IndexOf("."); 

    if (index > 0) 
     output = output.Substring(0, index); 

    listBox1.Items.Add("Bus: " + output); 
} 


//Show every ExpectedDepartureTime 
//If there is no expectedTime take value AimedDepartureTime 
foreach (var expH in expHours) 
{ 
    string output = expH.Substring(expH.IndexOf('T') + 1); 
    int index = output.IndexOf("."); 

    if (index > 0) 
     output = output.Substring(0, index); 

    lstHours.Items.Add(output); 
} 

爲是更清楚瞭解我的XML響應,下面是我的XML響應示例(其中一個帶有AimedDeparturetime和Expected,另一個帶有預期的)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<Siri version="1.0" xmlns="http://www.siri.org.uk/"> 
<ServiceDelivery> 
<ResponseTimestamp>2013-03-26T16:09:48.181Z</ResponseTimestamp> 
<StopMonitoringDelivery version="1.0"> 
<ResponseTimestamp>2013-03-26T16:09:48.181Z</ResponseTimestamp> 
<RequestMessageRef>12345</RequestMessageRef> 

<MonitoredStopVisit> 
<RecordedAtTime>2013-03-26T16:09:48.181Z</RecordedAtTime> 
<MonitoringRef>020035811</MonitoringRef> 
<MonitoredVehicleJourney> 
<FramedVehicleJourneyRef> 
<DataFrameRef>-</DataFrameRef> 
<DatedVehicleJourneyRef>-</DatedVehicleJourneyRef> 
</FramedVehicleJourneyRef> 
<VehicleMode>bus</VehicleMode> 
<PublishedLineName>2</PublishedLineName> 
<DirectionName>Elstow P+R</DirectionName> 
<OperatorRef>STB</OperatorRef> 
<MonitoredCall> 
<AimedDepartureTime>2013-03-26T16:11:00.000Z</AimedDepartureTime> 
<ExpectedDepartureTime>2013-03-26T16:11:28.000Z</ExpectedDepartureTime> 
</MonitoredCall> 
</MonitoredVehicleJourney> 
</MonitoredStopVisit> 
--------------------------------------------------- 

<MonitoredStopVisit> 
<RecordedAtTime>2013-03-26T16:09:48.181Z</RecordedAtTime> 
<MonitoringRef>020035811</MonitoringRef> 
<MonitoredVehicleJourney> 
<FramedVehicleJourneyRef> 
<DataFrameRef>-</DataFrameRef> 
<DatedVehicleJourneyRef>-</DatedVehicleJourneyRef> 
</FramedVehicleJourneyRef> 
<VehicleMode>bus</VehicleMode> 
<PublishedLineName>53</PublishedLineName> 
<DirectionName>Wootton</DirectionName> 
<OperatorRef>STB</OperatorRef> 
<MonitoredCall> 
<AimedDepartureTime>2013-03-26T16:19:00.000Z</AimedDepartureTime> 
</MonitoredCall> 
</MonitoredVehicleJourney> 
</MonitoredStopVisit> 
</StopMonitoringDelivery> 
</ServiceDelivery> 
</Siri> 

因此,目前我的應用程序不顯示公交車的每個出發時間。

我該如何解決這個問題?

謝謝!

回答

3

道歉的前期,因爲這是不是最大的XML解析過,但我會調整我的LINQ查詢:

var buses = from tblBuses in documentRoot.Descendants(ns + "MonitoredVehicleJourney") 
      select new 
        { 
         LineName = tblBuses.Descendants(ns + "PublishedLineName").Single().Value, 
         AimedHours = tblBuses.Descendants(ns + "AimedDepartureTime").Single().Value, 
         ExpectedHours = tblBuses.Descendants(ns + "ExpectedDepartureTime").Select(el => el.Value).SingleOrDefault() 
        }; 

這將創造出一些匿名類型,它允許您訪問總線的數據更多的是IEnumerable容易在後續代碼:

foreach (var bus in buses) 
{ 
    // Take ExpectedHours, or AimedHours if the first is null 
    string expH = bus.ExpectedHours ?? bus.AimedHours 

    // Same code as before here 
    string output = expH.Substring(expH.IndexOf('T') + 1); 
    int index = output.IndexOf("."); 
    if (index > 0) 
     output = output.Substring(0, index); 
    lstHours.Items.Add(output); 
} 

在你原來的代碼,即沒有一個<ExpectedDepartureTime>從未迭代,因爲他們從來沒有在你的expHours列表中顯示出來總線。相反,這個LINQ查詢將包含所有總線。它假定它們都有一個<AimedDepartureTime>和一個可選的<ExpectedDepartureTime>

對於預計的出發時間,我使用Select來獲取每個後代的元素值。使用SingleOrDefault().Value無法使用,因爲該查詢可能不會產生任何元素,並且將在null引用上調用get_Value()

關於我的查詢的最後一條評論:對於生產代碼,我不會使用Descendants並對XML結構進行更嚴格的查詢。

+0

re'SingleOrDefault()。Value' - 因此,您應該將'XElement'強制轉換爲'string'而不是使用'Value'。 – 2013-03-26 20:05:38

+0

這也是一個選擇;它會使代碼更清晰一些,但不一定更清晰。小調挑剔:它不只是一個演員,而是一個轉換。 – Thorarin 2013-03-26 21:34:53

+0

非常感謝!這對我有用! – 2013-03-27 09:30:00

2

你可以做一個LINQ查詢裏面的一切,並使用?:條件操作符來選擇正確的輸出:

var buses = 
    (from tblBuses in documentRoot.Descendants(ns + "PublishedLineName") 
    let bus = tblBuses.Value 
    let output = bus.Substring(bus.IndexOf('T') + 1) 
    let index = output.IndexOf(".") 
    select (index > 0) ? output.Substring(0, index) : output); 

foreach (var bus in buses) 
{ 
    listBox1.Items.Add("Bus: " + bus); 
} 

甚至

var buses = 
    (from ... 
    select "Bus: " + ((index > 0) ? output.Substring(0, index) : output)); 
    .ToArray(); 

listBox1.Items.AddRange(buses); 

同樣的模式可以應用到expHours

+0

這並沒有真正解決如果'expectedTime'爲空時如何選擇'AimedDepartureTime'的問題。 – 2013-03-26 21:20:17