2013-03-26 40 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