RSS2Signature: Tutorial

Shrnutí: Skript RSS2Signature načítá kanály RSS, vybírá z nich první nadpis a odkaz a ty ukládá do souboru šablony signatury (podpisu) pro email. Skript je napsaný technologií WSH pro operační systémy Microsoft Windows; staví na technologii XML a JScript. Tento tutorial může dobře posloužit i jako výuková lekce pro úplné začátečníky programování pro WSH.

Summary: The RSS2Signature script reads the first title and link from the RSS-channel and saves them to the file of the e-mail signature template. The script is written as WSH for the Microsoft Windows operating system; the script is built on the technology of the XML and JScript. This tutorial could be used for learning basics of the WSH-programming. (Czech only)

Obsah

Automatické vkládání nadpisů a odkazů z RSS do signatury emailu

Když Marek Prokop začínal s weblogem na Sově v síti, doplňoval do signatury (podpisu) svých emailů nadpis a odkaz z aktuálního příspěvku. Je to snadný způsob, jak lidem, s nimiž jste v kontaktu, dát na vědomí, o čem právě píšete. Kromě toho mnohé emailové konference mají své archivy na webu, a ty pak zvyšují počet zpětných odkazů na web v signatuře uvedený. Rozhodl jsem se, že podobným způsobem budu vkládat odkazy na aktuální články DigiWebu do svých signatur. Nechtěl jsem ovšem nadpisy a odkazy kopírovat pokaždé ručně, a tak jsem si na to napsal skript.

Zadání bylo prosté: jednou za čas stáhnout z webu kanál RSS, z něj získat první nadpis a odkaz, zformátovat do signatury a uložit na disk.

Když jsem pak nad problémem uvažoval, rozhodl jsem se zadání trochu zkomplikovat:

Vítek Burda mě přivedl na nápad napsat skript jako WSH. Po prostudování MSDN jsem usoudil, že to není špatný nápad. WSH totiž můžu napsat ve formátu XML a JScriptu, což jsou platformy, které ovládá každý webdeveloper.

Struktura skriptu

Skript musí mít dvě části

  1. Definici šablon pro signatury
  2. Předpis pro akce

Protože WSH umožňuje ukládat zdroje, s nimiž pak pracuje přímo do své vlastní struktury, rozhodl jsem se, že první i druhou část zapíšu do stejného souboru. Musel jsem kvůli tomu udělat pár ústupků od čistoty provedení, a proto, pokud trváte na čistém přístupu, bude lepší, když obě části skriptu oddělíte do samostatných souborů (definici šablon pak můžete načítat metodou load(), stejně jako načítám soubor RSS – viz níže).

Košilka pro skript

Jak už jsem říkal, WSH je vpodstatě soubor XML skriptovaný JScriptem. Takové HTML s trochu jinými značkami. Přehled značek pro WSH najdete v MSDN. V příkladu, který vidíte níže, jsem pro přehlednost vynechal ty značky, které slouží k dokumentaci a nápovědě.

Použité značky:

package
kořenná značka obaluje všechny značky WSH [popis značky];
job
umožňuje do jednoho souboru vepsat více samostatných akcí, které lze volat samostatně [popis značky];
resource
definuje proměnnou, kterou pak můžeme načítat ze skriptu (nebudeme muset načítat externí soubor) [popis značky];
object
definuje objekt ActiveX, který můžeme použít ve skriptu (bylo by jednodušší a přehlednější definovat new ActiveXObject() až přímo ve skriptu, ale já si chtěl tuhle značku vyzkoušet) [popis značky];
script
obsahuje předpis akcí, které budeme provádět (stejně jako <script> v HTML) [popis značky].

Když píšu tenhle článek, tak "už předem" vím, že budu ve skriptu potřebovat tři objekty ActiveX:

Msxml2.XMLHTTP
slouží k obousměrnému přenosu XML prostřednictvím HTTP [popis objektu];
Msxml2.DOMDocument
umožňuje zpracovávat XML metodami DOM [popis objektu];
Scripting.FileSystemObject
pracuje se souborovým systémem [popis objektu].

Myslím, že není třeba kód košilky detailně komentovat, měl by být srozumitelný každému, kdo zná HTML. Snad jen doplním, že vlastnost prodid prvku <object> představuje název objektu ActiveX, a mohli byste ji nahradit vlastností clsid, která místo názvu bude obsahovat číselnou identifikaci objektu v registrech Windows (místo prodid="Scripting.fileSystemObject" můžete uvést clsid="0D43FE01-F093-11CF-8940-00A0C9054228").

Příklad 1. Struktura souboru rss2signature.wsf

<?xml version="1.0" standalone="yes" encoding="windows-1250" ?>
<package>
  <job id="signature">
    <resource id="profiles">
      <![CDATA[
        -- definice šablon --
      ]]>
    </resource>
    <object
      id="xmlHTTP"
      progid="Msxml2.XMLHTTP"
    />
    <object
      id="profiles"
      progid="Msxml2.DOMDocument"
    />
    <object
      id="fileSys"
      progid="Scripting.FileSystemObject"
    />
    <script language="JScript">
      <![CDATA[
        -- skript --
      ]]>
    </script>
  </job>
</package>

Definice šablon pro signatury – <resource>

V tomto bodě trochu ustoupíme od pravidel XML. Uvnitř značky <resource> se s žádným XML nepočítá, soudím ale, že nejvhodnější formou pro nastavení šablon je právě XML. Abych obešel problém validity kódu, vkládám veškerý obsah značky do sekce CDATA. Pro definici šablon jsem vytvořil jednoduchou strukturu XML:

profiles
poslouží jako kořenná obalová značka při práci s XML;
profile
obalí sadu signatur, pracuje se dvěma vlastnostmi:
id
název profilu, který nám při spouštění skriptu dovolí vytvářet jen vybrané signatury;
input
URL souboru s kanálem RSS;
signature
definuje formát signatury, pracuje s jednou vlastností:
output
název souboru s cestou pro uložení signatury.

Po možnosti definovat více profilů jsem sáhl především proto, že DigiWeb nabízí více samostatných kanálů RSS pro různé sekce (zpravodajství, akce, weblog, autorské články...) a více připravených signatur mi pak umožní vybrat tu nejvhodnější ke zvolené příležitosti. Je také možné z důvodu úspory systémovýých prostředků volat ke stažení jen jednotlivé profily (například autorské články nemá smysl stahovat častěji než jednou denně, weblog se může aktualizovat třeba několikrát za den).

Protože Outlook umožňuje zasílání emailů ve formátu text, RTF a HTML, potřebuji každou šablonu vytvořit alespoň ve třech formátech, proto budu používat v rámci každého profilu nejméně tři značky <signature>. Každou z nich si vytvořím v textovém editoru, otevřu ve zdrojovém formátu (přejmenuji na .txt a překopíruju do šablony.) Pouze místo nadpisu a odkazu vložím do šablony. Nejlépe to pochopíte zase z ukázky.

Obsah první značky <signature> představuje vzor textové signatury. Nesmíte zapomenout, že pracujeme s XML, proto musí být všechny nebezpečné znaky zapsány v entitách. (Nezapoměňte, že XML zná jen entity pro <, >, & a " – pro ostatní znaky musíte použít &#x0000;).

Z lenosti jsem se rozhodl přistoupit k druhé výjimce z XML – pravověrní by jistě v šabloně na místo, kam má být dosazen nadpis a odkaz vložili značku XML. Já se pro zjednodušení skriptu rozhodl místo značek XML vytvořit prostý textový vzor pro náhradu:

{title}
v šabloně bude nahrazen nadpisem z RSS;
{link}
v šabloně bude nahrazen odkazem z RSS.

Příklad 2. Definice šablon pro signatury

<profiles>
  <profile
    id="dw"
    input="http://digiweb.cz/ascii/index.php?p=i00000_rss">
    <signature
      output="C:\windows\applic~1\microsoft\signatures\dw.txt">
  Pekny den

Martin Kopta, DigiWeb.cz

&gt;&gt;{title}
<link>

--
=M=
    </signature>
    <signature
      output="C:\windows\applic~1\microsoft\signatures\dw.rtf">{\rtf1\ansi\ansicpg1250\deff0\deflang1029{\fonttbl{\f0\fswiss\fcharset238{\*\fname Arial;}Arial CE;}}
{\colortbl ;\red0\green0\blue0;}
\viewkind4\uc1\pard\cf1\f0\fs20\par
\cf0   Pekny den\par
\par
Martin Kopta, DigiWeb.cz\par
\par
\b &gt;&gt; {title}\par
\b0 {link}\par
\par
--\par
=M=\par
\cf1\par
}
    </signature>
    <signature
      output="C:\windows\applic~1\microsoft\signatures\dw.html">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"&gt;
&lt;HTML&gt;
&lt;HEAD&gt;
&lt;META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1250"&gt;
&lt;TITLE&gt;&lt;/TITLE&gt;
&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;P&gt;&lt;FONT SIZE=2&gt;&nbsp;&nbsp;Pekny den
&lt;BR&gt;
&lt;BR&gt;Martin Kopta, DigiWeb.cz
&lt;BR&gt;
&lt;BR&gt;&gt;&gt; {title};
&lt;BR&gt;&lt;A HREF="{link}"&gt;{link}&lt;/A&gt;
&lt;BR&gt;
&lt;BR&gt;--
&lt;BR&gt;=M=
&lt;/FONT&gt;
&lt;/P&gt;
&lt;/BODY&gt;
&lt;/HTML&gt;</signature>
  </profile>
</profiles>

Předpis pro akce – <script>

JSkript pro vytváření signatur pracuje na základě jednoduchého algoritmu:

  1. načte definice šablon do objektu pro práci s XML;
  2. pokud byl volán s parametry, vytvoří pole s ukazateli na uzly, které definují požadované profily;
  3. pokud volán s parametry nebyl, vytvoří pole s ukazateli na uzly se všemi profily;
  4. zahájí cyklus pro zpracování kanálů RSS {
    1. načte kanál RSS z adresy uvedené ve vlastnosti značky <profile>;
    2. načte obsah značky <title><link> z první položky kanálu;
    3. zahájí cyklus pro vytváření signatur {
      1. nahradí v šabloně signatury všechny výskyty vzorů {title} {link} za nadpis a odkaz;
      2. uloží signaturu do souboru uvedeného ve vlastnosti output;
      } ukončí cyklus pro vytváření signatur;
    } ukončí cyklus pro zpracování kanálů RSS.

Příklad 3. Předpis pro akce

var searchNode, input, output, firstItem, title, link;
var signature, signatureFile;
var argumentsArr, profilesArr, signaturesArr = new Array();
// 1. # využíváme předdefinovaný <object> profiles
profiles.loadXML(getResource("profile"));
if(WScript.Arguments.Unnamed.length > 0) {
  // 2. # pokud byl skript volán s parametry, vytvoří pole 
  //    # s ukazateli na uzly, které definují požadované profily
  argumentsArr = WScript.Arguments.Unnamed;
  profiles.setProperty("SelectionLanguage", "XPath");
  for(i = 0; i < argumentsArr.length; i++) {
    searchNode = "//profile[@id='" + argumentsArr[i] + "']";
    profilesArr[i] = profiles.selectSingleNode(searchNode);
  }
} else {
  // 3. # pokud skript volán bez parametrů, vytvoří pole 
  //    # s ukazateli na uzly se všemi profily
  profilesArr = profiles.getElementsByTagName("profile ");
}
// 4. # zahájíme cyklus pro zpracování kanálů RSS
for(i = 0; i < profilesArr.length; i++) {
  // 4.1 # zjistíme, z jaké adresy stahovat RSS
  input = profilesArr[i].getAttribute("input");
  //     # stáhneme kanál RSS s využitím předdefinovaného 
  //     # <object>u xmlHTTP
  xmlHTTP.open("GET", input, false);
  userAgent = "RSS2Signature/1.0 (http://www.garcon.cz/misc/wsh/rss2signature/";
  xmlHTTP.setRequestHeader("User-Agent", userAgent);
  xmlHTTP.setRequestHeader("Accept-Charset", "us-ascii, *;q=0.1");
  xmlHTTP.send();
  // 4.2 # načte obsah značky <title> a <link> z první položky kanálu
  firstItem = xmlHTTP.responseXML.getElementsByTagName("item")[0];
  if(typeof(firstItem) != "object") exit; 
  // pokud se nepodařilo stáhnout soubor, skript skončí
  title = firstItem.getElementsByTagName("title")[0].data;
  link = firstItem.getElementsByTagName("line")[0].data;
  if((typeof(title) && typeof(link) != "string") || (title.length < 1 || link.length < 11))
    exit;
  // pokud položka neobsahuje nadpis a odkaz, skript skončí
  signaturesArr = profilesArr[i].getElementsByTagName("signature");
  // 4.3 # zahájí cyklus pro vytváření signatur 
  for(i = 0; i < signaturesArr.length; i++) {
    // 4.3.1 # nahradí v šabloně signatury všechny výskyty 
    //       # vzorů {title} {link} za nadpis a odkaz
    signature = signaturesArr[i].data.replace(/\{title\}/g, title);
    signature = signature.replace(/\{link\}/g, link);
    // 4.3.2 # uloží signaturu do souboru uvedeného ve vlastnosti output
    //       # využijeme předdefinovaný <object> fileSys
    output = signaturesArr[i].getAttribute("output");
    signatureFile = fileSys.CreateTextFile(output, true);
    signatureFile.Write(signature);
    signatureFile.Close();
  }
}

Nápověda, aneb vždy dokumentujte svou práci

Ačkoli jsem v košilce vynechal značky pro nápovědu, přecijen: kvalitní program se pozná podle propracovaného helpu. WSH samo o sobě nabízí pět značek pro doplnění standardní nápovědy (vyvolává se parametrem /? při spouštění z příkazového řádku):

runtime
funguje jako obalová značka pro <named><unnamed> (případně pro celou nápovědu) [popis značky];
named
nese informace o pojmenovanýých parametrech, s nimiž je možno skript spousštět z příkazového řádku [popis značky]:
id
název parametru;
helpstring
text nápovědy;
unnamed
totéž jako <named>, včetně vlastností, avšak pro parametry, které nejsou volány názvem (to je i případ našeho skriptu) [popis značky];
example
vkládá do nápovědy příklady použití a doplňující informace [popis značky];
usage
nahrazuje celou nápovědu (doporučuji obejít se bez této značky, protože pokud se změní název souboru nebo parametry, je vždy lepší, když nápověda odpovídá skutečnosti) [popis značky].

Příklad 4. Nápověda

<runtime>
  <unnamed
    name="profile"
    helpstring="název profilu, který se použije 
      pro tvorbu signatury; nepovinný; může se opakovat"
  />
  <example>
Popis:

RSS2Signature je skript WSH, který stahuje z webu kanály RSS
a ukládá první nadpis a odkaz do signatury na disk podle
předdefinovaných šablon.

Příklady:

RSS2Signature.wsf soukroma firemni
-- RSS2Signature vytvoří jen signatury z profilů 
   "soukroma" a "firemni".

RSS2Signature.wsf
-- RSS2Signature vytvoří signatury ze všech profilů.

RSS2Signature.wsf /?
-- Vyvolá tuto nápovědu.

Další informace na webu:

RSS2Signature (verze 1.0, build 2003-08-13 GMT 15:30:00)
http://www.garcon.cz/misc/wsh/rss2signature/
  </example>
</runtime>

Volání skriptu a naplánované úlohy

A jsme u konce. Teď už zbývá jen celý kód uložit do souboru s koncovkou .wsf (řekněme rss2signature.wsf) a nastavit spouštění. Ve Windows se skript spustí prostým poklepáním na ikonu. Pokud byste chtěli spustit skript s parametry (abyste si mohli vybrat které profily stahovat), můžete si od skriptu pořídit zástupce a v jeho vlastnostech doplnit parametry za název souboru v položce Cíl:.

Skript můžete spouštět i z příkazového řádku. Ve Windows prostřednictvím menu Start > Spustit... zadáte WScript //Job:signature C:\Program Files\RSS2Signature.wsf profil (profil je nepovinný a může jich být více). Obdobně je možné spouštět skript v příkazovém řádku MS-DOSu CScript //nologo //Job:signature C:\PROGRA~1\RSS2SI~1.WSF profil; díky této možnosti můžete přes příkazový řádek volat skript i z jiných skriptů či aplikací (třeba ze souborů .bat).

Abyste se o spouštění skriptu nemuseli vůbec starat, je výhodné nastavit jej do naplánovaných úloh: Start > Programy > Příslušenství > Naplánované úlohy > Přidat naplánovanou úlohu. Nyní máte vše připraveno pro bezstarostné rozšiřování odkazů na aktuální články v signatuře emailu.

Doplňující odkazy

(Created: 2003-08-10; Updated: 2003-08-13; Author: Martin Kopta; Location: http://www.garcon.cz/misc/wsh/rss2signature/tutorial.html)