REXX : génération spécifique de fichier RSS
À noter
- Principe
- Il s’agit de récupérer et ordonner aussi bien que possible des résultats sportifs d’origines diverses. Voir le programme sommaire
- Mise en conformité
- Certains caractères ou groupes de caractères sont adaptés : &, <, ainsi que le double tiret (interdit en XML). Voir la routine NORMAL dans le programme ci-dessous.
- Fonctionnalités supplémentaires
- Alignement des chronos en 2e colonne. Les temps sont repérés en positionnant avant eux les caractères “\$”.
- Alignement des affiliations (ou autre, année de naissance etc.) en position 50. Cette information est repérée en positionnant devant les caractères “\#”.
- Pour les résultats français, alignement des catégories (codes du site de la Fédération Française d’Athlétisme) en colonne 80. Voir la routine CATEG.
- Alignement supplémentaire possible en position 90, en intercalant les caractères “\%”.
- Dans le titre :
- Dans les résultats F.F.A., le code région est placé automatiquement au début, avec un balisage spécial. Voir la routine REGION.
- Ibidem pour le code pays dans les autres résultats (routine PAYS).
- Résultats F.F.A. : le titre peut être constitué à partir des deux premières lignes (cf options en entrée du programme).
- Traîtement de l’encodage
- Les données lues sont en UTF-8, qui est un encodage de longueur variable. Les caractères accentués et certaines langues y occupent deux octets voire plus. C’est un sérieux inconvénient quand on veut compter les caractères pour aligner le texte en colonnes séparées : le nombre d’octets lus par le programme diffère de ce que le lecteur humain voit. Pour contourner le problème, les données son converties en UNICODE. Voir notre page Le codage des caractères.
Exemples
Remarques :
- Un simple point comme première ligne permet de mêler des résultats FFA avec d’autres dans le même fichier d’entrées.
- Dans les résultats japonais, on a ajouté une seconde séparation (séparateur \%) pour les temps intermédiaires.
La source d’origine :
. NED Tilburg 1 oct 2016, Championnats Hollande/Belgique, 9e 50km ** 50km M 1 Rob Tersteeg \#76 NED RWV \$4:42:06 1 2 Wilfried Van Bremen \#87 NED RWV \$5:22:41 2 3 Jack Koolen \#69 NED Unitas \$5:33:38 3 4 René Wakkee \#65 NED RWV \$5:39:11 4 5 Andrea Toth (F) \#71 HUN Honved \$5:47:00 ** 20km (Champ. Bel 20km W) 1 Rick Liesting \#77 NED OLAT \$1:37:58 2 Remco de Bruin \#64 NED LAT \$1:44:15 3 Annelies Sarrazin (F) \#81 BEL FLAC \$1:55:56 1 4 Myriam Nicolas (F) \#63 BEL SMAC \$2:00:58 2 http://www.tigch.nl/snelwandelen/index_2016.htm . JPN Nomi, 19 mar 2017, Asian 20km Championships, ** 20km M 1 MATSUNAGA DAISUKE 松永 大介マツナガ ダイスケ \#4 神奈川・東洋大学\%19:24 39:18 (19:54) 59:25 (20:07) \$1:19:40 (20:15) 2 KIM, Hyunsub キム・フンスブ \#KOR・韓国\%19:43 39:34 (19:51) 59:40 (20:06) \$1:19:50 (20:10) 0:10 3 NODA TOMOHIRO 野田 明宏ノダ トモヒロ \#3 大阪・明治大学\%19:51 39:43 (19:52) 59:52 (20:09) \$1:20:04 (20:12) 0:24 4 SHEIKO, Georgiy ゲオルギー・シェイコ \#KAZ・カザフスタン\%19:54 40:04 (20:10) 1:00:27 (20:23) \$1:20:47 (20:20) 1:07 5 TAKUMI SAITO 西塔 拓己サイトウ \#タクミ愛知・愛知製鋼\%19:52 39:48 (19:56) 59:54 (20:06) \$1:20:56 (21:02) 1:16 6 KOLOTHUM THODI, Irfan イルファン・コロトゥム トージ \#IND・インド\%19:51 39:55 (20:04) 1:00:28 (20:33) \$1:20:59 (20:31) 1:19 7 OIKAWA FUMITAKA 及川 文隆オイカワ フミタカ \#3 愛知県・東洋大学\%19:51 39:48 (19:57) 1:00:13 (20:25) \$1:21:08 (20:55) 1:28 8 YAMANISHI Toshikazu ヤマニシ・トシカズ \#JPN・日本\%19:34 39:34 (20:00) 1:00:03 (20:29) \$1:21:23 (21:20) 1:43 ** 20km W 1 WANG Na ワン・ナ \#CHN・中国\%22:41 44:56 (22:15) 1:07:40 (22:44) \$1:30:51 (23:11) 2 ASADA CHIAKI 淺田 \#千安芸アサダ チアキ福岡・DNP西日本\%22:56 45:51 (22:55) 1:09:03 (23:12) \$1:32:12 (23:09) 1:21 3 YOSHIZUMI YUKI 吉住 友希ヨシズミ ユキ \#3 千葉・千葉県立保健医療大学\%22:56 45:51 (22:55) 1:09:03 (23:12) \$1:32:23 (23:20) 1:32 4 KAWAZOE KAORI 河添 香織カワゾエ カオリ \#3 京都・立命館大学\%22:48 45:40 (22:52) 1:09:04 (23:24) \$1:33:09 (24:05) 2:18 5 OKADA Kumiko オカダ・クミコ \#JPN・日本\%22:48 45:39 (22:51) 1:09:03 (23:24) \$1:33:21 (24:18) 2:30 6 YANG, Peili ヤン・ペイリ \#CHN・中国\%22:56 45:52 (22:56) 1:09:26 (23:34) \$1:34:18 (24:52) 3:27 DNF JEON, Yeongeun ジョン・ヨンクン \#KOR・韓国\%22:48 45:51 (23:03) 1:09:26 (23:35) DSQ RYKOVA, Regina レジーナ・リコワ \#KAZ・カザフスタン\%23:30 47:13 (23:43) 1:11:08 (23:55) \$1:35:45 (24:37) 4:54 http://www.jaaf.or.jp/taikai/1395/ 16/10/16 - Championnats Promotion Interclubs Cadets/Juniors BRIVE LA GAILLARDE - LIM ** 3000m / TCF 9:51 1 14'17"04 TERREC Eloise \#Ac Roche-sur-yon JUF/98 2 16'33"36 MANARESI Marion \#Ac Romorantin CAF/00 3 16'55"12 LARROZE-LAUGA Pauline \#Adour Pyrenees Athletisme 65 CAF/00 4 17'19"68 PEDROT Mylene \#Athletisme Sud 22 CAF/00 5 17'29"95 THRO Capucine \#Fac Andrezieux JUF/98 6 19'55"56 NOEL Emilie \#Ea Bourg-en-bresse CAF/00 ** 5000m / TCM 9:13 1 23'15"52 HALOUA BOUKHRIS Zineddine (ESP) \#Athle 66 JUM/98 2 23'56"81 BRACHET Thomas \#Afa Feyzin-venissieux JUM/98 3 24'12"72 GRELLIER Hugo \#Ac Roche-sur-yon CAM/99 4 26'54"07 VERDIERE Baptiste \#Stade Lavallois CAM/00 http://bases.athle.com/asp.net/liste.aspx?frmbase=resultats&frmmode=1&frmespace=0&frmcompetition=189816
Le fichier obtenu :
Remarque : le décallage des colonnes en caractères japonais est dû au fait qu’on n’utilise pas une police de type « monospace ».
<?xml version="1.0" encoding="utf-8"?> <rss version="2.0" xmlns="http://blogs.law.harvard.edu/tech/rss" xmlns:dg="http://ns.dg77.net/XML/" xmlns:d="http://ns.dg77.net/XML/d/" > <dg:description> <dg:cre></dg:cre> <dg:upd></dg:upd> </dg:description> <channel> <title></title> <description></description> <link></link> <lastBuildDate></lastBuildDate> <item> <guid isPermaLink="false">world-617</guid> <title><dg:span class="monosp">NED</dg:span> Tilburg 1 oct 2016, Championnats Hollande/Belgique, 9e 50km</title> <description dg:format="pre">** 50km M 1 4:42:06 Rob Tersteeg 76 NED RWV 1 2 5:22:41 Wilfried Van Bremen 87 NED RWV 2 3 5:33:38 Jack Koolen 69 NED Unitas 3 4 5:39:11 René Wakkee 65 NED RWV 4 5 5:47:00 Andrea Toth (F) 71 HUN Honved ** 20km (Champ. Bel 20km W) 1 1:37:58 Rick Liesting 77 NED OLAT 2 1:44:15 Remco de Bruin 64 NED LAT 3 1:55:56 Annelies Sarrazin (F) 81 BEL FLAC 1 4 2:00:58 Myriam Nicolas (F) 63 BEL SMAC 2 </description> <link>http://www.tigch.nl/snelwandelen/index_2016.htm</link> <pubDate></pubDate></item> <item> <guid isPermaLink="false">world-618</guid> <title><dg:span class="monosp">JPN</dg:span> Nomi, 19 mar 2017, Asian 20km Championships, </title> <description dg:format="pre">** 20km M 1 1:19:40 MATSUNAGA DAISUKE 松永 大介マツナガ ダイスケ 4 神奈川・東洋大学 19:24 39:18 (19:54) 59:25 (20:07) (20:15) 2 1:19:50 KIM, Hyunsub キム・フンスブ KOR・韓国 19:43 39:34 (19:51) 59:40 (20:06) (20:10) 0:10 3 1:20:04 NODA TOMOHIRO 野田 明宏ノダ トモヒロ 3 大阪・明治大学 19:51 39:43 (19:52) 59:52 (20:09) (20:12) 0:24 4 1:20:47 SHEIKO, Georgiy ゲオルギー・シェイコ KAZ・カザフスタン 19:54 40:04 (20:10) 1:00:27 (20:23) (20:20) 1:07 5 1:20:56 TAKUMI SAITO 西塔 拓己サイトウ タクミ愛知・愛知製鋼 19:52 39:48 (19:56) 59:54 (20:06) (21:02) 1:16 6 1:20:59 KOLOTHUM THODI, Irfan イルファン・コロトゥム トージ IND・インド 19:51 39:55 (20:04) 1:00:28 (20:33) (20:31) 1:19 7 1:21:08 OIKAWA FUMITAKA 及川 文隆オイカワ フミタカ 3 愛知県・東洋大学 19:51 39:48 (19:57) 1:00:13 (20:25) (20:55) 1:28 8 1:21:23 YAMANISHI Toshikazu ヤマニシ・トシカズ JPN・日本 19:34 39:34 (20:00) 1:00:03 (20:29) (21:20) 1:43 ** 20km W 1 1:30:51 WANG Na ワン・ナ CHN・中国 22:41 44:56 (22:15) 1:07:40 (22:44) (23:11) 2 1:32:12 ASADA CHIAKI 淺田 千安芸アサダ チアキ福岡・DNP西日本 22:56 45:51 (22:55) 1:09:03 (23:12) (23:09) 1:21 3 1:32:23 YOSHIZUMI YUKI 吉住 友希ヨシズミ ユキ 3 千葉・千葉県立保健医療大学 22:56 45:51 (22:55) 1:09:03 (23:12) (23:20) 1:32 4 1:33:09 KAWAZOE KAORI 河添 香織カワゾエ カオリ 3 京都・立命館大学 22:48 45:40 (22:52) 1:09:04 (23:24) (24:05) 2:18 5 1:33:21 OKADA Kumiko オカダ・クミコ JPN・日本 22:48 45:39 (22:51) 1:09:03 (23:24) (24:18) 2:30 6 1:34:18 YANG, Peili ヤン・ペイリ CHN・中国 22:56 45:52 (22:56) 1:09:26 (23:34) (24:52) 3:27 NF JEON, Yeongeun ジョン・ヨンクン KOR・韓国 22:48 45:51 (23:03) 1:09:26 (23:35) DQ 1:35:45 RYKOVA, Regina レジーナ・リコワ KAZ・カザフスタン 23:30 47:13 (23:43) 1:11:08 (23:55) (24:37) 4:54 </description> <link>http://www.jaaf.or.jp/taikai/1395/</link> <pubDate></pubDate></item> <item> <guid isPermaLink="false">test-00619</guid> <title><dg:span class="monosp">LIM</dg:span> BRIVE LA GAILLARDE - 16/10/16 - Championnats Promotion Interclubs Cadets/Juniors</title> <description dg:format="pre">** 3000m / TCF 9:51 1 14'17"04 TERREC Eloise Ac Roche-sur-yon JUF/98 2 16'33"36 MANARESI Marion Ac Romorantin CAF/00 3 16'55"12 LARROZE-LAUGA Pauline Adour Pyrenees Athletisme 65 CAF/00 4 17'19"68 PEDROT Mylene Athletisme Sud 22 CAF/00 5 17'29"95 THRO Capucine Fac Andrezieux JUF/98 6 19'55"56 NOEL Emilie Ea Bourg-en-bresse CAF/00 ** 5000m / TCM 9:13 1 23'15"52 HALOUA BOUKHRIS Zineddine (ESP) Athle 66 JUM/98 2 23'56"81 BRACHET Thomas Afa Feyzin-venissieux JUM/98 3 24'12"72 GRELLIER Hugo Ac Roche-sur-yon CAM/99 4 26'54"07 VERDIERE Baptiste Stade Lavallois CAM/00 </description> <link>http://bases.athle.com/asp.net/liste.aspx?frmbase=resultats&frmmode=1&frmespace=0&frmcompetition=189816</link> <pubDate></pubDate></item> </channel> </rss>
Le programme
Remarques :
- Au début, appel d’une routine externe testendian.rex. Cf rexxendian.htm.
- Sur fond jaune : instructions de traîtement UNICODE et problèmes connexes.
- Sur fond bleu : méthodes d’alignement de différentes colonnes.
- Sur fond vert : gestion d'un compteur maintenu dans un fichier simple texte.
/* REXX - Ce programme dispose le contenu d'un fichier texte dans un fichier RSS 2.0 Cf ~/tekno/manuel/rexxrss2.htm Ce programme est censé lire un fichier encodé en UTF-8 Voir autres commentaires à la fin */ /* INITIALISATIONS //////////////////////////////////////////////// */ parse source src.1 src.2 src.3 /* Monitorage des erreurs */ SIGNAL ON ERROR NAME erreur SIGNAL ON HALT NAME erreur SIGNAL ON SYNTAX NAME erreur OKF = 0 /* 1=au moins une ligne non vide */ CALL INITEM endian = '' ; blanx = '' CALL testendian.rex /* Module externe */ PARSE VAR RESULT endian blanx /* récupère un caractère espace hexadecimal UNICODE */ /* ENTREE DES PARAMETRES //////////////////////////////////// */ parse arg fentree fsortie prefixe numero ptitr IF fentree == "" then do say " Fichier lu ? " ; parse pull fentree /* parse : pour garder les caractères minuscules */ end IF fentree == "" then do say 'Aucun nom de fichier d''entree' say 'No input file name' pull exit end IF LINES(fentree) == 0 then do say 'Le fichier d''entree ' fentree ' est vide ou inexistant' say 'Input file ' fentree 'is empty or nonexistent' pull exit end IF fsortie == "" then do say " Fichier sorti ? " ; parse pull fsortie end IF fsortie == "" THEN exit IF prefixe == "" then do say " Prefixe ? " ; parse pull prefixe end if prefixe == "" | DATATYPE(prefixe, N) = 1 then do zontrav = "D-" || prefixe prefixe = zontrav end /* Compteur mis dans un enregistrement (lecture) */ IF (numero == "") | (DATATYPE(numero, N) = 1) THEN DO f_num = linein('marche/news/news_src/news_num.txt') PARSE VAR f_num fnum . if DATATYPE(fnum, N) then numero = fnum say 'Precedent no utilise / previous number : ' numero IF numero == "" then do say " Premier numero a utiliser ? " ; pull numero end if (numero == "") | (DATATYPE(numero, N) = 0) THEN numero = 1 IF ptitr == "" then do say " Titre sur 2 lignes O/(n=defaut) ? " ; pull ptitr /* pull : convertit en majuscules */ end /* BOUCLE DE LECTURE DU FICHIER //////////////////////////////////// */ DO while lines(fentree)>0 lig_ent = linein(fentree) nonblanc = wordindex(lig_ent,1) if nonblanc = 0 then do /* Ligne vide */ if ITEM = 1 THEN CALL FINITM end ELSE if wordindex(ligne,1) > 0 THEN CALL lig_trait ligne = lig_ent end /* FIN DE FICHIER ATTEINTE */ IF ITEM = 1 THEN CALL FINITM IF OKF = 1 then do CALL lineout fsortie, '</channel>' CALL lineout fsortie, '</rss>' end /* Compteur mis dans un enregistrement (sortie) */ CALL lineout 'marche/news/news_src/news_num.txt', numero, 1 say 'Dernier numero / last number : ' numero EXIT /* FIN DU PROGRAMME */ /* //////////////////////////////////////////////////////////////////// */ /* TRAITEMENT D'UNE LIGNE (titre ou detail) */ LIG_TRAIT: IF OKF=0 THEN CALL DEB /* 1ere sortie : mettre les entetes */ IF ITEM = 0 then do CALL lineout fsortie, '<item>' ITEM = 1 end IF (ptitr = 'O' & TITR = 1) | (ptitr \= 'O' & TITR = 0) then do /* L2 */ /* Debut de l'item */ if numero \= 0 then do CALL lineout fsortie, ' <guid isPermaLink="false">'prefixe || numero'</guid>' numero = numero + 1 end if ptitr = 'O' then do /* Titre avec 2 premieres lignes */ CALL REGION CALL PAYS CALL NET ltitre = ligne || ZTITRE CALL lineout fsortie, '<title>'ltitre'</title>' end else do /* Titre dans la premiere ligne */ CALL PAYS CALL NET CALL lineout fsortie, ' <title>'ligne'</title>' end TITR = 2 end else do /* L2 */ if ptitr = 'O' & TITR=0 then do /* L3 */ CALL NORMAL if ligne \== '.' THEN ZTITRE = ' ' || ligne TITR = 1 end else do /* L3 - Apres le titre : on sort les lignes de la partie description */ if DESCR = 0 THEN CALL charout fsortie, ' <description dg:format="pre">' DESCR = 1 CALL NORMAL if substr(ligne,1,1) \=="*" then do /* Mise en 2e colonne des données précédées par "\$" */ posl = POS('\$',ligne) if posl > 0 then do long = LENGTH(ligne) zsep = WORDINDEX(ligne, 2) -1 if zsep > 0 then do poslf = POS(' ',ligne,posl) trav2 = SUBSTR(ligne,1,zsep-1) if poslf == 0 THEN trav2 = trav2 || ' ' || SUBSTR(ligne,posl+2,long-posl-1) ELSE trav2 = trav2 || ' ' || SUBSTR(ligne,posl+2,poslf-posl-2) trav2 = trav2 || ' ' || SUBSTR(ligne,zsep+1,posl-zsep-1) || ' ' if poslf > 0 THEN trav2 = trav2 || SUBSTR(ligne,poslf+1,long-poslf) ligne = trav2 end end parse var ligne zon1 suite zontrav = zon1 ltrav = LENGTH(zon1) if ltrav > 1 & SUBSTR(zon1,ltrav) == '.' THEN zontrav = SUBSTR(zon1, 1, ltrav - 1) if DATATYPE(zontrav, N) = 1 then do /* 1ere colonne est un no classement */ if zontrav > 0 & zontrav < 10 THEN ligne = ' ' || zontrav || ' ' || suite if zontrav > 9 & zontrav < 100 THEN ligne = ' ' || zontrav || ' ' || suite if zontrav > 99 & zontrav < 1000 THEN ligne = zontrav || ' ' || suite end else do /* Cas ou la 1ere colonne n'indique pas le classement */ if DATATYPE(SUBSTR(zon1,1,1), N) = 0 then do if zon1 == 'DSQ' THEN zon1 = 'DQ' if zon1 == 'DNF' THEN zon1 = 'NF' if zon1 == 'DQ' | zon1 == 'NF' | zon1 == 'AB' | zon1 == 'NS' | , zon1 == 'NP' | zon1 == 'NC' | zon1 == 'HC' | zon1 == 'HM' , then do ligne = ' ' || zon1 || ' ' || suite trav = WORDINDEX(suite, 1) if trav > 0 then do if DATATYPE(SUBSTR(suite, trav, 1),N) = 0 then do cold = WORDINDEX(ligne, 2) if cold > 0 then CALL DECAL16 /* Aligne en position 16 la 2e colonne */ end end end end end cold = WORDINDEX(ligne, 3) /* Aligne en position 16 la 3e colonne */ col2 = WORDINDEX(ligne, 2) if cold > 0 then do if DATATYPE(SUBSTR(ligne, col2, 1),N) = 0 then do PARSE VAR ligne . z2 . if z2 == 'NC' | z2 == '*hb*' then call DECAL16 end else CALL DECAL16 end end /* Decalage en position 49 du 1er car après "\#" */ CALL ALIGNE '\#', 50, ligne CALL REMPLACE '\#', '' /* Decalage en position 79 du 1er car après "\%" */ CALL ALIGNE '\%', 80, ligne CALL REMPLACE '\%', '' /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ posisep = 0 if substr(ligne,1) \== "*" THEN CALL CATEG /* Aligne categories FFA */ CALL lineout fsortie, STRIP(ligne,T) /* strip ,t supprime les blancs de fin */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ end /* L3 */ end /* L2 */ RETURN /* ///////////////////////////// ROUTINES /////////////////////////////// */ DECAL16: /* - - - - - - - - - - - - - - - - - - */ if cold < 16 then do sep = 17 - cold tampon = '' if sep > 0 then do sep tampon = tampon || '20'x end zontrav = SUBSTR(ligne, 1, cold-2) || tampon || SUBSTR(ligne, cold) ligne = zontrav end RETURN DEB: /* - - - - - - - - - - - - - - - - - - */ OKF = 1 /* - Sort Tags de debut */ CALL lineout fsortie, '<?xml version="1.0" encoding="utf-8"?>' CALL lineout fsortie, '<rss version="2.0" ' CALL lineout fsortie, 'xmlns="http://blogs.law.harvard.edu/tech/rss"' CALL lineout fsortie, 'xmlns:dg="http://ns.dg77.net/XML/" ' CALL lineout fsortie, 'xmlns:d="http://ns.dg77.net/XML/d/" ' CALL lineout fsortie, '>' CALL lineout fsortie, '<dg:description>' CALL lineout fsortie, ' <dg:cre></dg:cre>' CALL lineout fsortie, ' <dg:upd></dg:upd>' CALL lineout fsortie, '</dg:description>' CALL lineout fsortie, '<channel>' CALL lineout fsortie, ' <title></title>' CALL lineout fsortie, ' <description></description>' CALL lineout fsortie, ' <link></link>' CALL lineout fsortie, ' <lastBuildDate></lastBuildDate>' CALL lineout fsortie, '' RETURN /* ********************************************************************** */ /* Termine description */ FDESC: CALL lineout fsortie, '</description>' DESCR = 0 RETURN /* ********************************************************************** */ /* Termine un item */ FINITM: IF SUBSTR(ligne, 1, 7) = 'http://' | SUBSTR(ligne, 1, 7) = 'https:/' then do if DESCR = 1 THEN CALL FDESC CALL NORMAL CALL lineout fsortie, '<link>'ligne'</link>' end ELSE if DESCR=1 then do CALL LIG_TRAIT CALL FDESC end CALL charout fsortie, '<pubDate></pubDate>' CALL lineout fsortie, '</item>' CALL lineout fsortie, '' CALL INITEM RETURN /* ********************************************************************** */ INITEM: ITEM = 0 /* 1=sortie d'un item commencee */ TITR = 0 /* 1=2e partie memorisee ; 2=le titre de l'item est sorti */ DESCR = 0 /* 1=sortie description commencee */ ZTITRE = '' ligne = '' RETURN /* ********************************************************************** */ /* Alignement (donnees en UNICODE pour avoir nombre fixe d'octets) */ ALIGNE: parse arg cod, col, chaine CALL CONV8_16 cod cod16 = sortie lcod = (LENGTH(cod16)) CALL CONV8_16 chaine chain16 = sortie posisep = POS(cod16, chain16) IF posisep > 0 & posisep < 2*col then do travf = posisep - 1 travl = 2*col - travf - lcod if posicat > 0 then lcod = 0 /* On conserve la chaine de recherche si categorie FFA */ tampon = '' if travl > 3 then do travl/2 tampon = tampon || x2c(blanx) end zone = SUBSTR(chain16, 1, travf) || tampon || SUBSTR(chain16, posisep + lcod) chain16 = zone posicat = 0 end CALL CONV16_8 chain16 ligne = sortie RETURN /* ********************************************************************** */ /* Conversion UTF-8 - UNICODE */ CONV8_16: parse arg entree sortie = '' ZONESORTIE.='NUL'; ZONESORTIE.0=0 /* nom suivi d'un point : c'est un "STEM" */ err = systounicode(entree, 'UTF8', , ZONESORTIE.) IF err == 0 THEN sortie = ZONESORTIE.!TEXT ELSE sortie = 'probleme car. ' || err RETURN /* ********************************************************************** */ /* Conversion UTF-16 - UNICODE */ CONV16_8: parse arg entree sortie = '' ZONESORTIE.='NUL'; ZONESORTIE.0=0 err = sysfromunicode(entree, 'UTF8', , ' ', ZONESORTIE.) IF err == 0 THEN sortie = ZONESORTIE.!TEXT ELSE sortie = 'probleme car. ' || err RETURN /* ********************************************************************** */ /* Normalise des chaines de caractere */ NORMAL: CALL REMPLACE '&', '&' CALL REMPLACE '--', '- - ' CALL REMPLACE '<', '<' CALL REMPLACE "''", '"' CALL REMPLACE '09'x, ' ' /* Tabulation */ CALL REMPLACE '1 000m Marche', '** 1000m' CALL REMPLACE '2 000m Marche', '** 2000m' CALL REMPLACE '3 000m Marche', '** 3000m' CALL REMPLACE '5 000m Marche', '** 5000m' CALL REMPLACE '10 000m Marche', '** 10.000m' CALL REMPLACE '20 000m Marche', '** 20.000m' CALL REMPLACE '30 000m Marche', '** 30.000m' CALL REMPLACE '50 000m Marche', '** 50.000m' CALL REMPLACE '10 Km Marche', '** 10km' CALL REMPLACE '20 Km Marche', '** 20km' CALL REMPLACE '35 Km Marche', '** 35km' CALL REMPLACE '50 Km Marche', '** 50km' CALL REMPLACE '100 Km Marche', '** 100km' CALL REMPLACE '10 Minutes Marche', '** 10mn' CALL REMPLACE '20 Minutes Marche', '** 20mn' CALL REMPLACE '30 Minutes Marche', '** 30mn' CALL REMPLACE '45 Minutes Marche', '** 45mn' CALL REMPLACE '1 heure Marche', '** 1 heure' CALL REMPLACE '1 Heure Marche', '** 1 heure' CALL REMPLACE '24 heures Marche', '** 24h' CALL REMPLACE '24 Heures Marche', '** 24h' CALL REMPLACE 'Grand Fond Marche', '** Grand Fond' RETURN /* ********************************************************************** */ /* Supprime inutile (dans titre) */ NET: CALL REMPLACE '\$', '' CALL REMPLACE '\#', '' CALL REMPLACE '\%', '' CALL REMPLACE '09'x, ' ' /* Tabulation */ RETURN /* ********************************************************************** */ /* Remplace toute chaine1 par chaine2 dans ligne */ REMPLACE: parse arg chaine1, chaine2 long1 = LENGTH(chaine1) apres = ligne ligne = '' avant = '' DO while apres \= '' numcar = POS(chaine1,apres) if numcar=0 then do ligne = ligne || apres leave end avant = avant || substr(apres,1,numcar-1) || chaine2 ligne = avant numcar = numcar+long1 apres = substr(apres,numcar) end RETURN /* ********************************************************************** */ REGION: flag = 0 CALL LIGF "- I-F" ; if flag \= 0 THEN RETURN CALL LIGF "- ARA" ; if flag \= 0 THEN RETURN CALL LIGF "- AQU" ; if flag \= 0 THEN RETURN CALL LIGF "- BFC" ; if flag \= 0 THEN RETURN CALL LIGF "- CEN" ; if flag \= 0 THEN RETURN CALL LIGF "- G-E" ; if flag \= 0 THEN RETURN CALL LIGF "- H-F" ; if flag \= 0 THEN RETURN CALL LIGF "- N-A" ; if flag \= 0 THEN RETURN CALL LIGF "- N-C" ; if flag \= 0 THEN RETURN CALL LIGF "- NOR" ; if flag \= 0 THEN RETURN CALL LIGF "- OCC" ; if flag \= 0 THEN RETURN CALL LIGF "- P-L" ; if flag \= 0 THEN RETURN CALL LIGF "- PCA" ; if flag \= 0 THEN RETURN CALL LIGF "- PYF" ; if flag \= 0 THEN RETURN CALL LIGF "- COR" ; if flag \= 0 THEN RETURN CALL LIGF "- GUA" ; if flag \= 0 THEN RETURN CALL LIGF "- GUY" ; if flag \= 0 THEN RETURN CALL LIGF "- MAR" ; if flag \= 0 THEN RETURN CALL LIGF "- MAY" ; if flag \= 0 THEN RETURN CALL LIGF "- REU" ; if flag \= 0 THEN RETURN CALL LIGF "- W-F" ; if flag \= 0 THEN RETURN CALL LIGF "- _ET" ; if flag \= 0 THEN RETURN /* Pourrait devenir utile un jour */ CALL LIGF "- _HF" ; if flag \= 0 THEN RETURN /* Pourrait devenir utile un jour */ /* Codes ligues obsoletes depuis 2017 */ CALL LIGF "- ALS" ; if flag \= 0 THEN RETURN CALL LIGF "- AUV" ; if flag \= 0 THEN RETURN CALL LIGF "- B-N" ; if flag \= 0 THEN RETURN CALL LIGF "- BOU" ; if flag \= 0 THEN RETURN CALL LIGF "- BRE" ; if flag \= 0 THEN RETURN CALL LIGF "- C-A" ; if flag \= 0 THEN RETURN CALL LIGF "- CHA" ; if flag \= 0 THEN RETURN CALL LIGF "- F-C" ; if flag \= 0 THEN RETURN CALL LIGF "- H-N" ; if flag \= 0 THEN RETURN CALL LIGF "- LAN" ; if flag \= 0 THEN RETURN CALL LIGF "- LIM" ; if flag \= 0 THEN RETURN CALL LIGF "- LOR" ; if flag \= 0 THEN RETURN CALL LIGF "- NPC" ; if flag \= 0 THEN RETURN CALL LIGF "- P-F" ; if flag \= 0 THEN RETURN CALL LIGF "- PIC" ; if flag \= 0 THEN RETURN CALL LIGF "- POI" ; if flag \= 0 THEN RETURN CALL LIGF "- PRO" ; if flag \= 0 THEN RETURN CALL LIGF "- PYR" ; if flag \= 0 THEN RETURN CALL LIGF "- R-A" RETURN /* ********************************************************************** */ LIGF: parse arg codlig posdeb = POS(codlig,ligne) IF posdeb \== 0 then do flag = 1 za = LEFT(ligne,posdeb) zb = SUBSTR(ligne,posdeb + 5) ligne = '<dg:span class="monosp">' || SUBSTR(codlig,3,3) || '</dg:span> ' || za || zb end RETURN /* ********************************************************************** */ PAYS: if SUBSTR(ligne,4,1) == ' ' then do p = SUBSTR(ligne,1,3) IF p='AFG' | p='ALB' | p='ALG' | p='AND' | p='ANG' | p='ANT' | p='ARG' | p='ARM' | p='ARU' | p='ASA' | p='AUS' | , p='AUT' | p='AZE' | p='BAH' | p='BAN' | p='BAR' | p='BDI' | p='BEL' | p='BEN' | p='BER' | p='BGU' | p='BHU' | , p='BIH' | p='BIZ' | p='BLR' | p='BOL' | p='BOT' | p='BRA' | p='BRN' | p='BRU' | p='BUL' | p='BUR' | p='CAF' | , p='CAM' | p='CAN' | p='CAY' | p='CHA' | p='CHI' | p='CHN' | p='CIV' | p='CGO' | p='CMR' | p='COD' | p='COK' | , p='COL' | p='COM' | p='CPV' | p='CRC' | p='CRO' | p='CUB' | p='CYP' | p='CZE' | p='DEN' | p='DJI' | p='DMA' | , p='DOM' | p='ECU' | p='EGY' | p='ERI' | p='ESA' | p='ESP' | p='EST' | p='ETH' | p='FIJ' | p='FIN' | p='FRA' | , p='FSM' | p='GAB' | p='GAM' | p='GBR' | p='GBS' | p='GEO' | p='GEQ' | p='GER' | p='GHA' | p='GRE' | p='GRN' | , p='GUA' | p='GUI' | p='GUM' | p='GUY' | p='HAI' | p='HKG' | p='HON' | p='HUN' | p='INA' | p='IND' | p='IRI' | , p='ISL' | p='ISR' | p='ISV' | p='ITA' | p='IVB' | p='JAM' | p='JOR' | p='JPN' | p='KAZ' | p='KEN' | p='KGZ' | , p='KIR' | p='KOR' | p='KSA' | p='KUW' | p='LAO' | p='LAT' | p='LBA' | p='LBR' | p='LCA' | p='LES' | p='LIB' | , p='LIE' | p='LTU' | p='LUX' | p='MAD' | p='MAR' | p='MAS' | p='MAW' | p='MDA' | p='MDV' | p='MEX' | p='MGL' | , p='MHL' | p='MKD' | p='MLI' | p='MLT' | p='MNE' | p='MON' | p='MOZ' | p='MRI' | p='MTN' | p='MYA' | p='NAM' | , p='NCA' | p='NED' | p='NEP' | p='NGR' | p='NIG' | p='NOR' | p='NRU' | p='NZL' | p='OMA' | p='PAK' | p='PAN' | , p='PAR' | p='PER' | p='PHI' | p='PLE' | p='PLW' | p='PNG' | p='POL' | p='POR' | p='PRK' | p='PUR' | p='QAT' | , p='ROU' | p='RSA' | p='RUS' | p='RWA' | p='SAM' | p='SEN' | p='SEY' | p='SIN' | p='SKN' | p='SLE' | p='SLO' | , p='SMR' | p='SOL' | p='SOM' | p='SRB' | p='SRI' | p='STP' | p='SUD' | p='SUI' | p='SUR' | p='SVK' | p='SWE' | , p='SWZ' | p='SYR' | p='TAN' | p='TGA' | p='THA' | p='TJK' | p='TKM' | p='TLS' | p='TOG' | p='TPE' | p='TTO' | , p='TUN' | p='TUR' | p='TUV' | p='UAE' | p='UGA' | p='UKR' | p='URU' | p='USA' | p='UZB' | p='VAN' | p='VEN' | , p='VIE' | p='VIN' | p='YEM' | p='ZAM' | p='ZIM' then do xlig = '<dg:span class="monosp">' || SUBSTR(ligne,1,3) || '</dg:span>' || SUBSTR(ligne,4) ligne = xlig end end RETURN /* ********************************************************************** */ CATEG: CALL CATCAT "VEF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "VEM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V1F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V1M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V2F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V2M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V3F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "V3M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "SEF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "SEM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "ESF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "ESM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "JUF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "JUM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "CAF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "CAM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "MIF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "MIM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F35F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M35M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F40F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M40M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F45F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M45M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F50F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M50M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F55F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M55M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F60F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M60M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F65F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M65M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "BEF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "BEM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "POF/" ; if posicat \= 0 THEN RETURN CALL CATCAT "POM/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F70F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F75F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F80F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F85F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F90F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "F95F/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M70M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M75M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M80M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M85M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M90M/" ; if posicat \= 0 THEN RETURN CALL CATCAT "M95M/" RETURN /* ********************************************************************** */ CATCAT: parse arg codcat posicat = POS(codcat, ligne) IF posicat > 0 & posicat < 90 then do CALL ALIGNE codcat, 90, ligne end RETURN /* ********************************************************************** */ erreur: phrase = 'Probleme avec programme ' || src.3 ' ligne ' || SIGL || ' - ' sourceline(SIGL) say phrase IF POS('OS/400', src.1) > 0 then do /* IBM AS400 - iSeries */ 'CHGDTAARA DTAARA(*LDA (201 328)) VALUE('''phrase''')' EXIT end else do /* Windows */ if POS('WIN', src.1) > 0 then do say phrase pull RETURN phrase end ELSE say phrase pull RETURN phrase end /* *************************************************************** Ce programme dispose dans un fichier RSS 2.0 le contenu d'un fichier texte Cf ~/tekno/manuel/rexxrss2.htm Groupes de lignes ("items") : - 1 ou 2 lignes : Titre - n lignes : Détail - dernière ligne (facultatif) Lien http etc. Pour les resultats fournis par le site FFA athle.org, deux lignes de début sont mises en une seule (option "O") Deplacement du code region ou pays en debut de ligne de titre Au moins une ligne vide entre chaque item Alignement automatique - Categories FFA : posi 90 - \$ mis en 2e colonne : chrono - \# (position 50) affiliation, naissance… - \% (position 80) reste… */