Ad van der Kolk


Ad van der Kolk

Content, content, content...Waar halen we het vandaan?!

Altijd een probleem. Je moet een demosite optuigen met echte mensenwereld content. Dus naar Google Nieuws Search en een paar RSS feeds opsporen. En dan begint het. Knippen en plakken in de Manager. Veel werk, RSI, en saai. Maar het kan ook anders. Alle ingrediënten om zoiets te automatiseren hebben we al in de SXML toolbox. Het handigst is natuurlijk om van een RSS Feed, een XML bestand te maken en die in de manager te importeren. Probleem is dat je dan alleen de titel en de omschrijving hebt èn je moet handmatig de import doen. Dat is goed te doen maar geheel automatique is leuker.
Wat hebben we nodig. Een RSS Feed reader. Die hebben we: de macro feedreader. Een knipper en plakker. Hebben we ook: de combinatie embeduri, string en buffer gaat dat helemaal doen. Nu nog iets om een file te schrijven. Inderdaad, de relatief onbekende maar o zo handige filesystem vipers. Als laatste het konijn uit de hoed: de cmsWebservice waarmee je een asynchrone (xml)import kunt doen, zie de documentatie hierover.
Goed, het gereedschap hebben we. Nu het slachtoffer nog. Inderdaad: NU.nl is de bron voor allerlei nieuwsberichten die ze in RSS Feeds beschikbaar stellen. Over het juridische aspect stap ik maar heen. We gaan voor het experiment gewoon NU.nl rippen.
Allereerst de interface. Een eenvoudig formuliertje (helaas nog geen Xforms) waar je wat gegevens invoert. Kies de Feed, geef de folder waar de items komen te staan en geef de naam van het bestand waarin de XML wordt weggeschreven. 

Smartsite SXML CopyCode image Copy Code
<form id="readinput" class="form" method="post" action="{channel.link(GENEREERXML)}" enctype="multipart/form-data">
 <fieldset>
  <legend>Invoer</legend>
  <label for="Naam">Kies een NU.nl Feed</label>
  <select name="feed">
  <option value="http://www.nu.nl/feeds/rss/algemeen.rss">http://www.nu.nl/feeds/rss/algemeen.rss</option>
  <option value="http://www.nu.nl/feeds/rss/sport.rss">http://www.nu.nl/feeds/rss/sport.rss</option>
  <option value="http://www.nu.nl/feeds/rss/wetenschap.rss">http://www.nu.nl/feeds/rss/wetenschap.rss</option>
  <option value="http://www.nu.nl/feeds/rss/economie.rss">http://www.nu.nl/feeds/rss/economie.rss</option>
  <option value="http://www.nu.nl/feeds/rss/gezondheid.rss">http://www.nu.nl/feeds/rss/gezondheid.rss</option>
  <option value="http://www.nu.nl/feeds/rss/auto.rss">http://www.nu.nl/feeds/rss/auto.rss</option>
  <option value="http://www.nu.nl/feeds/rss/beurs.rss">http://www.nu.nl/feeds/rss/beurs.rss</option>
  <option value="http://www.nu.nl/feeds/rss/media.rss">http://www.nu.nl/feeds/rss/media.rss</option>
  <option value="http://www.nu.nl/feeds/rss/weer.rss">http://www.nu.nl/feeds/rss/weer.rss</option>
 
  <option value="http://www.nu.nl/feeds/rss/muziek.rss">http://www.nu.nl/feeds/rss/muziek.rss</option>
  <option value="http://www.nu.nl/feeds/rss/boek.rss">http://www.nu.nl/feeds/rss/boek.rss</option>
  <option value="http://www.nu.nl/feeds/rss/film.rss">http://www.nu.nl/feeds/rss/film.rss</option>
 
  <option value="http://www.nu.nl/feeds/rss/internet.rss">http://www.nu.nl/feeds/rss/internet.rss</option>
  <option value="http://www.nu.nl/feeds/rss/games.rss">http://www.nu.nl/feeds/rss/games.rss</option>
  <option value="http://www.nu.nl/feeds/rss/gadgets.rss">http://www.nu.nl/feeds/rss/gadgets.rss</option>
 
  <option value="http://www.nu.nl/feeds/rss/opmerkelijk.rss">http://www.nu.nl/feeds/rss/opmerkelijk.rss</option>
  <option value="http://www.nu.nl/feeds/rss/achterklap.rss">http://www.nu.nl/feeds/rss/achterklap.rss</option>
 
  <option value="http://www.nu.nl/feeds/rss/nudata.rss">http://www.nu.nl/feeds/rss/nudata.rss</option>
  <option value="http://www.nu.nl/feeds/rss/werk-en-prive.rss">http://www.nu.nl/feeds/rss/werk-en-prive.rss</option>
  </select>
  <br />
 
  <se:sitemap startitem="SI_NEWS" maxlevels="4" foldersonly="true" resulttype="datatable" save="dtfolders"/>
 
  <label for="Naam">Items opslaan onder:</label>
  {buffer.set(i,1)}
  <select name="folder">
    <se:for from="1" to="{datatable.rows.count($dtfolders)}">
      <option value="{datatable.getvalue($dtfolders,$i,'nr')}">{datatable.getvalue($dtfolders,$i,'title')}</option> 
      {buffer.set(i, $i+1)}
    </se:for>
  </select>
  <br />
  <label for="Naam">Geef bestandsnaam (zonder .xml)</label>
  <input id="Naam" name="Naam" type="text" size="50" value="{request.form(Naam)}" class="field" />
 </fieldset>
 
 <p class="buttons">
 <input class="button" type="submit" id="loadingButton" value="OK"/> 
 <input class="button" type="reset" value="Annuleren"/>
 </p>
</form>

Dan de verwerking van de op het formulier ingevoerde gegevens. Hier wordt basale (title, description, body en contenttype) import-XML gegeneerd door de feed in een datatable te zetten, deze uit te lezen en met de locationgegevens uit de RSS Feed (dit is de link naar het volledige bericht) met de embeduri macro en wat string vipers, de bodytekst uit het nieuwsbericht te knippen. De aldus verkregen XML schrijven we weg naar een bestand op het filesystem. Daarna starten we de import op met de cmsWebservice. Even wachten en kijk in de manager: nieuwe versie content in een oogwenk. Hieronder staat wat voorbeeldcode die je kunt gebruiken.

Smartsite SXML CopyCode image Copy Code
{buffer.set(feed,sys.iif(request.form(feed) == '','http://www.nu.nl/feeds/rss/algemeen.rss',request.form(FEED)))}
{buffer.set(naam,sys.iif(request.form(naam) == '','content',request.form(NAAM)))}
{buffer.set(path,'/import/')}
{buffer.set(filename,$naam + '.xml')}
{buffer.set(path_file,$path+$filename)}
{buffer.set(folder,request.form(FOLDER))}
{storage.set('XMLcontentimport','importxmlfile',$path_file)}
{storage.set('XMLcontentimport','importfolder',$folder)}
<se:feedreader location="{buffer.get(feed)}" maxrows="50" save="dtRSS" resulttype="datatable" />
{buffer.set(i,2)} <!--// We skip the first row -->
<se:buffer name="data" whitespace="normalize">
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;root&gt;
&lt;site&gt;
  <se:for from="2" to="{datatable.rows.count($dtRSS)}">
    {buffer.set(title,datatable.getvalue($dtRSS,$i,'title'))}
    {buffer.set(description,datatable.getvalue($dtRSS,$i,'description'))}
    {buffer.set(location,datatable.getvalue($dtRSS,$i,'location'))}
    <se:embeduri location="{datatable.getvalue($dtRSS,$i,'location')}" save="bodytxt" />
    {buffer.set(start, string.indexof($bodytxt, 'div class="content"'))}
    {buffer.set(end, string.indexof($bodytxt, 'end content div'))}
    {buffer.set(len,sys.eval($end - $start))}
    <se:if expression="$len GT 0 ">
    <se:then>
      {buffer.set(body,string.substring($bodytxt,$start+20,$len))}
    </se:then>
    <se:else>
      {buffer.set(body,"Geen Body tekst gevonden")}
    </se:else>
    </se:if>
&lt;page&gt;
&lt;title type="xsd:string"&gt;&lt;![CDATA[{buffer.get(title)}]]&gt;&lt;/title&gt;
&lt;description type="xsd:string"&gt;{buffer.get(description)}&lt;/description&gt;
&lt;body type="xsd:string"&gt;&lt;![CDATA[{buffer.get(body)}]]&gt;&lt;/body&gt;
&lt;contenttype code="NWS" storage="PS5CT.SimpleLookupStorage" key="1"&gt;News Page&lt;/contenttype&gt;
&lt;/page&gt;
    {buffer.set(i, $i + 1)}
</se:for>
&lt;/site&gt;
&lt;/root&gt;
</se:buffer>
{buffer.set(xml,string.encodeampersand(string.trim(string.xmldecode($data))))}
{filesystem.writetext($path_file, $xml)}
File: <a href="{buffer.get(path_file)}" >{buffer.get(path_file)}</a> aangemaakt.<br />
<br />
Klik <a href="{channel.link(IMPORTRSSXML)}" target="_blank">hier</a> om het XML Bestand te importeren in de site!
<br />
{buffer.set(filename,storage.get('XMLcontentimport','importxmlfile'))}
{buffer.set(folder,storage.get('XMLcontentimport','importfolder'))}
<br />
{buffer.get(filename)} - {buffer.get(folder)}
<br />
Nog een <a href="{channel.link(STARTGENEREERIMPORTXML)}" target="_blank">keer.</a>

De XML die gegenereerd wordt, ziet er zo uit:

 XML file Voorbeeld

Omdat we ingevoerde gegevens in global storage hebben opgeslagen, kunnen we die weer uitlezen en aanbieden aan de cmsWebservice voor de import. Code staat hieronder.

Smartsite SXML CopyCode image Copy Code
<!--// Get XML Filename and Import Folder item -->
{buffer.set(filename,storage.get('XMLcontentimport','importxmlfile'))}
{buffer.set(folder,storage.get('XMLcontentimport','importfolder'))}
<se:webservice url="{env.cmsserveraddress()}">
  <se:parameters>
    <se:parameter name="soapaction">http://smartsite.nl/cmsWebservice/action/cmsWebservice.ImportXmlAsync</se:parameter>
    <se:parameter name="username">xxnaam</se:parameter>
    <se:parameter name="password">xxpwd</se:parameter>
    <se:parameter name="literalmethodnode">
      <i:ImportXmlAsync xmlns:i="http://smartsite.nl/cmsWebservice/message/">
        <fileName>{buffer.get(filename)}</fileName>
        <parent>{buffer.get(folder)}</parent>
        <importSettings>
          <writeimportjob>true</writeimportjob>
          <importmode>3</importmode>
          <contentstatus>0</contentstatus>
          <deletesourcefiles>False</deletesourcefiles>
          <displaydetailedimportsummary>true</displaydetailedimportsummary>
        </importSettings>
      </i:ImportXmlAsync>
    </se:parameter>
  </se:parameters>
</se:webservice>

Natuurlijk, het is geen generieke oplossing. De kwaliteit van knippen en plakken is afhankelijk van de opbouw van bericht dat uitgelezen wordt. Het kan altijd beter. Dus als je tips hebt om de body van een pagina slim en automatisch te cleanen van bv scripting en andere vervelende tags, dan horen we dat graag. Maar vooralsnog kun je hiermee snel een berg content in je site importeren. Dat gezegd hebbende, kun je hiermee ook een bestaande Smartsite 5 site importeren. Vooral in situaties waarbij een iXperion en een Smartsite 5 site nog enige tijd naast elkaar blijven bestaan. Na de initiele import van content kun je de updates die nog in Smartsite 5 gedaan worden, via nette RSS feeds en de juiste instellingen van de importservice, importeren. Kijk nog wel even naar copyright zaken als je bestaande contentbronnen gaat gebruiken. Toch wel  belangrijk. Voor je het weet zit je achter de tralies. 

Posted by Ad van der Kolk on Friday, October 07, 2011 5:48:11 PM
You are not allowed to post here.
All Blogs
Johan Blok
Features, projects, ambitions
Ad van der Kolk
About van alles en nog wat
Vincent Baaij
Showing it, Making sites with it, Adapting it, Refining it, Telling about it, Selling it, Investigating it, Teaching it and Expanding it.
Johan den Ouden
Smartsite storyteller
Demian Buijs
The art of Smartsite iXperion
Marc Derksen
What is happening at Smartsite R&D.
Marc van Neerven
Marc's shared thoughts...
Twan Meijerink
About new projects, quality assurance and me ;-)
Douwe de Wilde
About security, maybe more...
Mike Perquin
About WCF, Outscaling, database maintenance (SQL server), etc.
René Pronk
while (true);
Erwin Rijss
About building sites and more...
Recent Blog Comments
Marc van Neerven
17 April 2012, 13:30
An issue has been reported that expanding of hyperlinks fails when immediately followed by '.' or ','....
Ruben Verschueren
30 January 2012, 15:31
I get an 'operation has timed out' error (even for the examples). however if I browse to the uri's...
Marc van Neerven
12 August 2011, 16:50
Added a new (Web-guidelines compliant) download.
Marc van Neerven
12 August 2011, 14:33
Just added an update (3.0) which produces compliant XHTML and has been adapted for strict Web Guidelines...
Johan den Ouden
10 August 2011, 10:38
Uiteraard is bovenstaande code ook in een virtual assembly te gieten zodat een dll niet meer noodzakelijk...

Profile
Latest additions
Smartsite iXperion 1.4 build 6 has been released! locked
Twan Meijerink, 01 May 2012, 14:42
Workbench beta has expired
Hank Brandwijk, 11 January 2012, 16:53
Smartsite iXperion 1.4 build 4 has been released! locked
Twan Meijerink, 02 December 2011, 11:04
The second life of XForms
Marc van Neerven, 04 November 2011, 18:34
How to hide a property in a custom module? locked
Peter van der Waal, 17 October 2011, 09:31
Microsoft Certified Partner Logo