|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example xmlpatterns/trafficinfo |
|
44 \title TrafficInfo Example |
|
45 |
|
46 Shows how XQuery can be used extract information from WML documents provided by a WAP service. |
|
47 |
|
48 \section1 Overview |
|
49 |
|
50 The WAP service used in this example is \l{Trafikanten}{wap.trafikanten.no} |
|
51 that is run by the Norwegian governmental agency for public transport in |
|
52 Oslo. The service provides real time information about the departure of |
|
53 busses, trams and undergrounds for every station in the city area. |
|
54 |
|
55 This example application displays the departure information for a specific |
|
56 station and provides the feature to filter for a special bus or tram line. |
|
57 |
|
58 \image trafficinfo-example.png |
|
59 |
|
60 \section1 Retrieving the Data |
|
61 |
|
62 Without the knowledge of XQuery, one would use QNetworkAccessManager to |
|
63 query the WML document from the WAP service and then using the QDom |
|
64 classes or QXmlStreamReader classes to iterate over the document and |
|
65 extract the needed information. |
|
66 However this approach results in a lot of glue code and consumes valuable |
|
67 developer time, so we are looking for something that can access XML |
|
68 documents locally or over the network and extract data according to given |
|
69 filter rules. That's the point where XQuery enters the stage! |
|
70 |
|
71 If we want to know when the underground number 6 in direction |
|
72 \Aring\c{}sjordet is passing the underground station in Nydalen on November |
|
73 14th 2008 after 1pm, we use the following URL: |
|
74 |
|
75 \c{http://wap.trafikanten.no/F.asp?f=03012130&t=13&m=00&d=14.11.2008&start=1} |
|
76 |
|
77 The parameters have the following meanings: |
|
78 \list |
|
79 \o \e{f} The unique station ID of Nydalen. |
|
80 \o \e{t} The hour in 0-23 format. |
|
81 \o \e{m} The minute in 0-59 format. |
|
82 \o \e{d} The date in dd.mm.yyyy format. |
|
83 \o \e{start} Not interesting for our use but should be passed. |
|
84 \endlist |
|
85 |
|
86 As a result we get the following document: |
|
87 |
|
88 \quotefile examples/xmlpatterns/trafficinfo/time_example.wml |
|
89 |
|
90 So for every departure we have a \c <a> tag that contains the time as a |
|
91 text element, and the following text element contains the line number |
|
92 and direction. |
|
93 |
|
94 To encapsulate the XQuery code in the example application, we create a |
|
95 custom \c TimeQuery class. This provides the \c queryInternal() function |
|
96 that takes a station ID and date/time as input and returns the list of |
|
97 times and directions: |
|
98 |
|
99 \snippet examples/xmlpatterns/trafficinfo/timequery.cpp 1 |
|
100 |
|
101 The first lines of this function synthesize the XQuery strings that fetch |
|
102 the document and extract the data. |
|
103 For better readability, two separated queries are used here: the first one |
|
104 fetches the times and the second fetches the line numbers and directions. |
|
105 |
|
106 The \c doc() XQuery method opens a local or remote XML document and returns |
|
107 it, so the \c{/wml/card/p/small/} statement behind it selects all XML nodes |
|
108 that can be reached by the path, \c wml \rarrow \c card \rarrow \c p \rarrow |
|
109 \c small. |
|
110 Now we are on the node that contains all the XML nodes we are interested in. |
|
111 |
|
112 In the first query we select all \c a nodes that have a \c href attribute |
|
113 starting with the string "Rute" and return the text of these nodes. |
|
114 |
|
115 In the second query we select all text nodes that are children of the |
|
116 \c small node which start with a number. |
|
117 These two queries are passed to the QXmlQuery instance and are evaluated |
|
118 to string lists. After some sanity checking, we have collected all the |
|
119 information we need. |
|
120 |
|
121 In the section above we have seen that an unique station ID must be passed |
|
122 as an argument to the URL for retrieving the time, so how to find out which |
|
123 is the right station ID to use? The WAP service provides a page for that |
|
124 as well, so the URL |
|
125 |
|
126 \c{http://wap.trafikanten.no/FromLink1.asp?fra=Nydalen} |
|
127 |
|
128 will return the following document: |
|
129 |
|
130 \snippet examples/xmlpatterns/trafficinfo/station_example.wml 0 |
|
131 |
|
132 The names of the available stations are listed as separate text elements |
|
133 and the station ID is part of the \c href attribute of the parent \c a |
|
134 (anchor) element. In our example, the \c StationQuery class encapsulates |
|
135 the action of querying the stations that match the given name pattern with |
|
136 the following code: |
|
137 |
|
138 \snippet examples/xmlpatterns/trafficinfo/stationquery.cpp 0 |
|
139 |
|
140 Just as in the \c TimeQuery implementation, the first step is to |
|
141 synthesize the XQuery strings for selecting the station names and the |
|
142 station IDs. As the station name that we pass in the URL will be input |
|
143 from the user, we should protect the XQuery from code injection by using |
|
144 the QXmlQuery::bindVariable() method to do proper quoting of the variable |
|
145 content for us instead of concatenating the two strings manually. |
|
146 |
|
147 So, we define a XQuery \c $station variable that is bound to the user |
|
148 input. This variable is concatenated inside the XQuery code with the |
|
149 \c concat method. To extract the station IDs, we select all \c a elements |
|
150 that have an \c title attribute with the content "Velg", and from these |
|
151 elements we take the substring of the \c href attribute that starts at the |
|
152 18th character. |
|
153 |
|
154 The station name can be extracted a bit more easily by just taking the |
|
155 text elements of the selected \a elements. |
|
156 |
|
157 After some sanity checks we have all the station IDs and the corresponding |
|
158 names available. |
|
159 |
|
160 The rest of the code in this example is just for representing the time and |
|
161 station information to the user, and uses techniques described in the |
|
162 \l{Widgets Examples}. |
|
163 */ |