issue115:freepascal
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue115:freepascal [2016/11/29 09:13] – créée d52fr | issue115:freepascal [2016/12/11 17:14] (Version actuelle) – andre_domenech | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | In this series of articles, I will be building a text-based application with Free Pascal, using its text-based interface for user interaction. This will be combined with other, more modern, technologies such as database access using SQL and Web access with HTTP. The final aim of the project is to demonstrate how Pascal can be used to build a modern application, | + | **In this series of articles, I will be building a text-based application with Free Pascal, using its text-based interface for user interaction. This will be combined with other, more modern, technologies such as database access using SQL and Web access with HTTP. The final aim of the project is to demonstrate how Pascal can be used to build a modern application, |
- | In the previous part of the series, we deviated a bit from Free Vision and went into the technical details on how to use the CURL library from Pascal to connect to an RSS feed on FCM’s content management system. At this stage, we know how to connect to the server and download an XML file containing a list of recent articles published on the web page. In this part, we will see how to parse the XML code to retrieve the information we are aiming for: issue numbers and download URLs. We will then put it all together, and update the database our application uses with fresh data from the Web. | + | In the previous part of the series, we deviated a bit from Free Vision and went into the technical details on how to use the CURL library from Pascal to connect to an RSS feed on FCM’s content management system. At this stage, we know how to connect to the server and download an XML file containing a list of recent articles published on the web page. In this part, we will see how to parse the XML code to retrieve the information we are aiming for: issue numbers and download URLs. We will then put it all together, and update the database our application uses with fresh data from the Web.** |
- | Understanding the XML language | + | Dans cette série d' |
+ | |||
+ | Dans l' | ||
+ | |||
+ | **Understanding the XML language | ||
EXtended Meta Language (XML) is a simple text-based language that aims to structure data as a tree: each data element may have none, or several child nodes. On the other hand, each element must have a single parent element - except for a single node in the entire tree, which is then called the root element. Each element should open with a start tag, such as < | EXtended Meta Language (XML) is a simple text-based language that aims to structure data as a tree: each data element may have none, or several child nodes. On the other hand, each element must have a single parent element - except for a single node in the entire tree, which is then called the root element. Each element should open with a start tag, such as < | ||
Ligne 9: | Ligne 13: | ||
Perhaps an example may help. If we wish to codify a library, for instance, our root element will be the library itself. This library may then contain an element defining its owner, and perhaps another giving the date on which the data set was compiled. Finally, we will need to create an element for each book in the library, giving its title and author. | Perhaps an example may help. If we wish to codify a library, for instance, our root element will be the library itself. This library may then contain an element defining its owner, and perhaps another giving the date on which the data set was compiled. Finally, we will need to create an element for each book in the library, giving its title and author. | ||
- | The beauty of this scheme is that it may easily be adapted for different purposes in a flexible manner. For instance, in the above example, one of the books has been marked with a genre, while another has not. | + | The beauty of this scheme is that it may easily be adapted for different purposes in a flexible manner. For instance, in the above example, one of the books has been marked with a genre, while another has not.** |
+ | |||
+ | Comprendre le langage XML | ||
+ | |||
+ | Le XML (EXtended Meta Language - Méta-langage étendu) est un langage simple en mode texte dont le but est de structurer les données sous forme d' | ||
+ | |||
+ | Peut-être qu'un exemple peut aider. Si nous souhaitons codifier une bibliothèque, | ||
+ | |||
+ | La beauté de ce schéma est qu'il peut être facilement adapté à différents sujets de manière flexible. Par exemple, dans le cas ci-dessus, un des livres a été marqué avec un genre et l' | ||
- | Writing a program to transverse a data set in XML has its own challenges; luckily for us, the Free Pascal project has foreseen the use of a set of standard classes that may be implemented for our own purposes. Let us write a simple program that reads in an XML file, and outputs on screen each element name in sequence, or its value if it is a text element that simply contains text. To begin with, let us include the standard and XML classes and define our variables (previous page, bottom right). | + | **Writing a program to transverse a data set in XML has its own challenges; luckily for us, the Free Pascal project has foreseen the use of a set of standard classes that may be implemented for our own purposes. Let us write a simple program that reads in an XML file, and outputs on screen each element name in sequence, or its value if it is a text element that simply contains text. To begin with, let us include the standard and XML classes and define our variables (previous page, bottom right). |
The TFileStream will be used to access the XML file on our local disk, and make it available to a TXMLReader through an adaptor class, TXMLInputSource. The TXMLReaderSettings object is needed to pass parameters to the reader. | The TFileStream will be used to access the XML file on our local disk, and make it available to a TXMLReader through an adaptor class, TXMLInputSource. The TXMLReaderSettings object is needed to pass parameters to the reader. | ||
We begin by configuring the settings, basically telling the reader to ignore supplementary whitespace (actual spaces, but also line breaks and tabulations), | We begin by configuring the settings, basically telling the reader to ignore supplementary whitespace (actual spaces, but also line breaks and tabulations), | ||
+ | |||
+ | settings := TXMLReaderSettings.Create; | ||
+ | |||
+ | settings.PreserveWhiteSpace := false; | ||
+ | |||
+ | settings.Namespaces := true;** | ||
+ | |||
+ | L' | ||
+ | |||
+ | TFileStream sera utilisé pour accéder au fichier XML sur le disque local et le rendre disponible à TXMLReader à travers une classe d' | ||
+ | |||
+ | Nous commençons par configurer les paramètres, | ||
settings := TXMLReaderSettings.Create; | settings := TXMLReaderSettings.Create; | ||
Ligne 23: | Ligne 47: | ||
settings.Namespaces := true; | settings.Namespaces := true; | ||
- | We access the file, and create a TXMLInputSource from the resulting stream: | + | **We access the file, and create a TXMLInputSource from the resulting stream: |
f := TFileStream.Create(' | f := TFileStream.Create(' | ||
Ligne 39: | Ligne 63: | ||
Parsing our RSS feed in XML | Parsing our RSS feed in XML | ||
- | In the last part of this series, we obtained the RSS for Full Circle Magazine using the CURL library. This is a piece of XML data, with the following structure. It has been cleaned up a bit to showcase relevant elements (shown below). | + | In the last part of this series, we obtained the RSS for Full Circle Magazine using the CURL library. This is a piece of XML data, with the following structure. It has been cleaned up a bit to showcase relevant elements (shown below).** |
- | So, what we want to do is isolate individual < | + | Nous accédons au fichier pour créer une TXMLInputSource du flux résultant : |
+ | |||
+ | f := TFileStream.Create(' | ||
+ | |||
+ | input := TXMLInputSource.Create(f); | ||
+ | |||
+ | Maintenant (voir ci-dessus), nous pouvons créer notre TXMLTextReader et lui faire analyser chaque élément rencontré. | ||
+ | |||
+ | Enfin, n' | ||
+ | |||
+ | f.Free; | ||
+ | |||
+ | Le code complet du programme est disponible ici : http:// | ||
+ | |||
+ | Analyser notre flux RSS en XML | ||
+ | |||
+ | Dans la partie précédente de cette série, nous avions obtenu le RSS du Full Circle Magazine en utilisant la bibliothèque CURL. Ce sont des données XML, avec la structure suivante. Il a été un peu nettoyé pour mieux souligner les éléments intéressants (voir ci-dessous). | ||
+ | |||
+ | **So, what we want to do is isolate individual < | ||
The first set are those used for the CURL library, the second will be the input and output streams to be parsed together, and the third set is for the XML parser. Finally, the two strings and associated boolean variables will be needed to link each element (of type ntElement) with its associated value (type ntText) - which is not the element itself, but a sub-element inserted inside the parent element. Unfortunately, | The first set are those used for the CURL library, the second will be the input and output streams to be parsed together, and the third set is for the XML parser. Finally, the two strings and associated boolean variables will be needed to link each element (of type ntElement) with its associated value (type ntText) - which is not the element itself, but a sub-element inserted inside the parent element. Unfortunately, | ||
We will not go over either the use of the CURL library, that has been described in the previous part of this series, or over the XML parser. We will concentrate instead on the use of the piped streams. We will create the two streams together: | We will not go over either the use of the CURL library, that has been described in the previous part of this series, or over the XML parser. We will concentrate instead on the use of the piped streams. We will create the two streams together: | ||
+ | |||
+ | CreatePipeStreams (inPipe, outPipe);** | ||
+ | |||
+ | Aussi, nous voulons isoler les éléments individuels < | ||
+ | |||
+ | Le premier jeu est celui utilisé pour la bibliothèque CURL, le second sera pour les flux d' | ||
+ | |||
+ | Nous n' | ||
CreatePipeStreams (inPipe, outPipe); | CreatePipeStreams (inPipe, outPipe); | ||
- | The CURL library can then be created using the outPipe section, to which it will write the data obtained from the Internet: | + | **The CURL library can then be created using the outPipe section, to which it will write the data obtained from the Internet: |
curl_easy_setopt(hCurl, | curl_easy_setopt(hCurl, | ||
Ligne 62: | Ligne 112: | ||
Integrating XML parsing into our Free Vision application | Integrating XML parsing into our Free Vision application | ||
- | At this stage, we have on the one hand a working Free Vision application, | + | At this stage, we have on the one hand a working Free Vision application, |
- | Perhaps the most elegant way of doing this - and the least expensive in terms of writing code - is to create a new Dialog type. Called TUpDateDialog, | + | La bibliothèque CURL peut ensuite être créée en utilisant la section outPipe, vers laquelle il écrira les données obtenues d' |
+ | |||
+ | curl_easy_setopt(hCurl, | ||
+ | |||
+ | L' | ||
+ | |||
+ | input := TXMLInputSource.Create(inPipe); | ||
+ | |||
+ | Enfin, la boucle principale du lecteur XML peut être configurée pour détecter les paires titre/lien. Pour l' | ||
+ | |||
+ | Le programme complet peut être trouvé ici : http:// | ||
+ | |||
+ | Intégrer l' | ||
+ | |||
+ | À ce stade, d'une part, nous avons une application Free Vision fonctionnelle, | ||
+ | |||
+ | **Perhaps the most elegant way of doing this - and the least expensive in terms of writing code - is to create a new Dialog type. Called TUpDateDialog, | ||
The TUpdateDialog will need no outside inputs, since it will always be using the same target URL to connect to the Internet, and local database filename to append any data found on new issues of FCM. This Dialog will just need a constructor that builds it, and sets off the process: | The TUpdateDialog will need no outside inputs, since it will always be using the same target URL to connect to the Internet, and local database filename to append any data found on new issues of FCM. This Dialog will just need a constructor that builds it, and sets off the process: | ||
Ligne 79: | Ligne 145: | ||
• Two pipes, to set up the connection between the incoming stream from the Internet, and an outgoing stream towards the XML reader. | • Two pipes, to set up the connection between the incoming stream from the Internet, and an outgoing stream towards the XML reader. | ||
• The XML reader itself, associated settings, and several variables to identify each new issue’s identification code (e.g. ‘111’), title (‘Full Circle Magazine #111’) and download link. | • The XML reader itself, associated settings, and several variables to identify each new issue’s identification code (e.g. ‘111’), title (‘Full Circle Magazine #111’) and download link. | ||
- | • A handler for the SQLite connection to the local database. | + | • A handler for the SQLite connection to the local database.** |
- | So, have a look at the code shown bottom right. | + | La façon peut-être la plus élégante de le faire - et la moins chère en écriture de code - est de créer un nouveau type Dialog. Appelé TUpDateDialog, |
+ | |||
+ | TUpDateDialog n'a besoin d' | ||
+ | |||
+ | TUpdateDialog = object(TDialog) | ||
+ | constructor Init (FileName : String); | ||
+ | end; | ||
+ | PUpdateDialog = ^TUpdateDialog; | ||
+ | |||
+ | Cette procédure de constructeur aura besoin d'un bon nombre de variables, mais elles peuvent être classées en catégories séparées. Il nous faudra : | ||
+ | • Un TRect et un PLabel pour paramétrer ce Dialog à l' | ||
+ | • Une URL et un PCurl pour aller sur Internet et récupérer un flux accédant aux informations du FCM. | ||
+ | • Deux tubes, pour préparer la connexion entre le flux d' | ||
+ | • Le lecteur XML lui-même, ses paramètres associés et plusieurs variables pour identifier le code d' | ||
+ | • Un gestionnaire pour la connexion de SQLite à la base de données locale. | ||
+ | |||
+ | |||
+ | **So, have a look at the code shown bottom right. | ||
Most of the code will not be reproduced here, since it is in essence a mashup of that written in our previous part and the beginning of this one. Salient points would include the use of a Regular Expression parser (regexp) in order to parse the titles from the XML stream, identifying which contain the text identifying a new issue of FCM. We are looking for something such as ‘#109’, ‘#110’, ‘# | Most of the code will not be reproduced here, since it is in essence a mashup of that written in our previous part and the beginning of this one. Salient points would include the use of a Regular Expression parser (regexp) in order to parse the titles from the XML stream, identifying which contain the text identifying a new issue of FCM. We are looking for something such as ‘#109’, ‘#110’, ‘# | ||
Ligne 91: | Ligne 174: | ||
We can now use ‘re’ as a regular expression reader in the following way, to identify if the next value found by the XML reader contains the expression we are looking for. If so, it can be isolated and used to prime the issue code for insertion into the database (shown bottm left). | We can now use ‘re’ as a regular expression reader in the following way, to identify if the next value found by the XML reader contains the expression we are looking for. If so, it can be isolated and used to prime the issue code for insertion into the database (shown bottm left). | ||
- | Now, all we need to do is determine, for each issue announcement found in the XML stream, if this issue is already inside our database. To so do, we will need to get back to the SQLite driver, and search the existing issues with the same identifying code. If a match is not found, this issue is a new one and needs to be appended to the existing table (shown top right). | + | Now, all we need to do is determine, for each issue announcement found in the XML stream, if this issue is already inside our database. To so do, we will need to get back to the SQLite driver, and search the existing issues with the same identifying code. If a match is not found, this issue is a new one and needs to be appended to the existing table (shown top right).** |
- | Once the XML code has been completely parsed, we can alter the label on the Dialog to notify the user of how many new issues of FCM have been found. In my case, my database had been initialized by hand with issues 108, 109 and 110. I launched the application, | + | Aussi, jetez un œil au code présenté ci-dessous. |
+ | |||
+ | La plupart du code ne sera pas reproduit ici , car c'est, au fond, un rabâchage de ce qui a été écrit dans notre article précédent et au début de celui-ci. Les points marquants sont l' | ||
+ | |||
+ | re := TRegExpr.Create; | ||
+ | |||
+ | re.Expression := '# | ||
+ | |||
+ | Nous pouvons utiliser maintenant « re » comme un lecteur d' | ||
+ | |||
+ | Maintenant, tout ce que nous avons à faire est de déterminer, | ||
+ | |||
+ | **Once the XML code has been completely parsed, we can alter the label on the Dialog to notify the user of how many new issues of FCM have been found. In my case, my database had been initialized by hand with issues 108, 109 and 110. I launched the application, | ||
msgLabel^.Text := NewStr(' | msgLabel^.Text := NewStr(' | ||
Ligne 101: | Ligne 196: | ||
The finalized application’s code can be found here: http:// | The finalized application’s code can be found here: http:// | ||
- | In this part of the series, we put our complete application together using Free Vision for the user interface, SQLite to create a local data, and CURL and XML to retrieve fresh data from an RSS feed from the Web to update our database. In the next part, we will see various ways in which our application can run on a Raspberry Pi. | + | In this part of the series, we put our complete application together using Free Vision for the user interface, SQLite to create a local data, and CURL and XML to retrieve fresh data from an RSS feed from the Web to update our database. In the next part, we will see various ways in which our application can run on a Raspberry Pi.** |
+ | |||
+ | Une fois le code XML complètement analysé, nous pouvons modifier l' | ||
+ | |||
+ | msgLabel^.Text := NewStr(' | ||
+ | |||
+ | | ||
+ | |||
+ | Le code final de l' | ||
+ | |||
+ | Dans cet article de la série, nous avons assemblé l' | ||
issue115/freepascal.1480407180.txt.gz · Dernière modification : 2016/11/29 09:13 de d52fr