0

バス番号、目的時間、予想時間を含むバス時間を表示するアプリケーションを作成しようとしています。

から(ライブ)情報を取得しHttpWebRequestます。リクエストからの応答は、XML形式の文字列変数に保存されます。

必要なすべての情報を入手できます。バスの時間、目的の時間、期待される時間のように。

問題は、予想時間がない場合は何も表示されないことです。予想時間がないときに、コードが目標時間と同じ値をとるのが好きです。

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応答の例を以下に示します(AimedDeparturetimeとExpectedを使用したものと、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>

したがって、現時点では、私のアプリケーションはバスのすべての出発時刻を表示しません。

どうすればこれを解決できますか?

ありがとう!

4

2 に答える 2

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>

予想される出発時間については、aを使用しSelectて各子孫の要素値を取得しました。クエリは要素を生成せず、参照で呼び出される可能性があるため、usingは使用SingleOrDefault().Valueできません。get_Value()null

私のクエリに関する最後のコメント:本番コードの場合Descendants、XML構造の使用を控え、より厳密なクエリを実行します。

于 2013-03-26T18:49:48.670 に答える
2

1つの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

于 2013-03-26T17:10:59.227 に答える