DekiScript - Aggregate data from tables

Pagina modificata 15:04, 4 Mag 2009 da wikiadmin | Cronologia

aggregate_tables.pngThis script extracts rows from tables placed in different pages and aggregates them in one tabular table.

This script use the power of Dekiscript combined with Lucene search engine and xpath language.

Concept

  • templates are wiki pages with one or more tables
  • any table has a unique caption identifier, caption is html text so it is indexed in search engine (and we can use it to restrict the number of pages to process)
  • any row as a unique css class, we use this to extract the text from cells

Algorithm

  • query a list of object pages, restrict them with the table caption keyword (example: tpl_mytable) and/or a path
  • use dekiscript and xpath to extract all tables with a specific css class name (example: tpl_mytable)
  • use dekiscript and xpath to extract de data form the secon columns and add it to a Dekiscript map object
  • print the map in a unique table

 This script use wiki.getsearch function so you must wait the new page to be indexed by Lucene.

Application

  • create an address-book and list contacts in an aggregate table
  • list projects informations

 

There is a discussion thread on MindTouc Forum

Code

Template 

Copy this EXAMPLE code in a wiki template page, html source (Es: Meeting), you can build any template you need. Remember to:

  • put an identifier in caption (es: tpl_meeting)
  • put unique css class in any row
<table width="100%" cellspacing="0" cellpadding="4" border="1" class="tpl_meeting">
    <caption>tpl_meeting</caption>
    <tbody>
        <tr>
            <td width="33%" bgcolor="#dddddd" class="oggetto">
            <p>Oggetto riunione</p>
            <p class="comment"><em>Obbligatorio</em></p>
            </td>
            <td>&nbsp;{{ edit: web.text(__request.args["copia"]) }}</td>
        </tr>
        <tr>
            <td bgcolor="#dddddd" class="data_riunione">
            <p>Data riunione</p>
            <p class="comment"><em>gg/mm/aaaa</em></p>
            </td>
            <td>&nbsp;{{ edit: web.text(__request.args["data"]) }}</td>
        </tr>
        <tr>
            <td bgcolor="#dddddd" class="partecipanti">
            <p>Partecipanti</p>
            <p class="comment"><em>nome.cognome</em></p>
            </td>
            <td>&nbsp;{{ edit: web.text(__request.args["partecipanti"]) }}</td>
        </tr>
        <tr>
            <td bgcolor="#dddddd" class="progetto">
            <p>Progetto</p>
            <p class="comment"><em>link alla pagina progetto</em></p>
            </td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td bgcolor="#dddddd" class="premesse_precedenti">
            <p>Premesse e precedenti</p>
            </td>
            <td>{{ edit: web.text(__request.args["agenda"]) }}</td>
        </tr>
    </tbody>
</table>

 

DekiScript code

Copy this code in a deki template page (example: XsysTableData) copy it in html source code editor

/*  Copyright (C) 2008 www.intertesto.com
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License http://www.gnu.org/licenses */ /* ---------------------------- Parameters passed to template: - templatename = name of the template page that we want to match in wiki pages - order = lucene order field - limit = search max results - table_key = string used in caption tag of html table, required to restrict number of pages - search = search string passed to wiki.getsearch - path = path passed to wiki.getsearch, if you wont to include descendent pages add an * at the end - fields = a list of css class applied to the row of the html template table - pagedata = (default false) if set to TRUE will add 2 extra columns with last page modification date and relative author, the page name will be expanded */ var error = FALSE; var listglobal = [ ]; var listsingle = []; var mapsingle = {} ; var tables; var key = ""; var cell=""; var fields = ""; var search = ""; var temp = ""; var msgsearch = ""; var limit = (args.limit ?? 1000);
var msglimit = "Limita i risultati ai primi "..limit;
var order = (args.order ?? "-date");
var msgorder = " Ordina secondo il campo "..order.." (il - indica decrescente)"; if (args.pagedata == "TRUE" ) {
var msg = "<p>Questa pagina aggrega i dati nel seguente modo:
<ul><li>"..msgsearch.."</li>
<li>Individua le pagine che contengono il modello "..args.templatename.."</li>
<li>estrae le righe di ogni tabella modello</li>
<li>"..msglimit..msgorder.."</li></ul> </p>";
web.toggle(web.xml("<html><body>"..msg.."</body></html>"),"Elenco "..args.templatename);
} if (string.length(args.table_key) == 0) {
web.html("<p>ERROR! Parameter table_key is required!</p>");
let error = TRUE;
} else {
let key = args.table_key;
}
var xpath = '//table[normalize-space(caption)=\''.. key ..'\']';

if (#args.templatename == 0 && #args.fields == 0 ) {
web.html("<p>ERROR! Parameter templatename or fields is required!</p>");
let error = TRUE;
} else if (#args.fields == 0) {
var page = wiki.page(args.templatename);
var tables = xml.list(page,xpath, nil, true);
let fields = xml.list(web.xml(tables[0]),'//tr/td[1]/@class',nil,false);
}

else {
let fields = args.fields;
}
if (#args.search == 0 && #args.path == 0) {
web.html("<p>ERROR! Arguments search or path is required!</p>");
let error = TRUE;
} else if ( #args.path != 0 ) {
let search = "path:"..string.replace(args.path, ':', '?').." AND content:"..args.table_key;
let msgsearch = "Cerca le pagine nel percorso: "..args.path;
} else {
let search = args.search;
let msgsearch = "Cerca le pagine con il comando: "..search;
}
var r = wiki.getsearch(search,limit,order);
if (#r == 0) {
web.html("<p>Nessuna pagina trovata!</p>");
let error = TRUE;
}

if (error == FALSE) {
foreach (var p in r) {
if (#p.path > 0) {
let tables = xml.list(wiki.Page(p.path),xpath, nil, true);
}
if (#tables[0] > 0 && p.path > 0) {
let listsingle = [];
let mapsingle = { };
let mapsingle ..= { 'pageid' : p.id };
let mapsingle ..= { 'pageuri' : p.uri };
let mapsingle ..= { 'pagetitle' : p.title };
let mapsingle ..= { 'pagedate' : p.date };
let mapsingle ..= { 'pagename' : p.name };
let mapsingle ..= { 'pageauthor' : p.author.name };
foreach ( var field in fields) {
var row = web.list(tables[0], '//tr[td[1]/@class=\''.. field ..'\']',nil,true);
if ( #row[0] > 0 ) {
        let cell = web.html(row[0],"/tr/td[2]",nil,true);
let cell = string.replace(cell,string.match(cell,"(<td[^>]*>)"),"");
let cell = string.replace(cell,string.match(cell,"(</td[^>]*>)"),"");
let cell = string.replace(cell,'"',"'");
let mapsingle ..= { (field) : cell };
}
}
let listglobal ..= [mapsingle];
}
}
}
/* ----- print map ------ */
if (args.action == "map" || args.action == "all") {
var a=1;
}

/* ------- print html table ----- */
if (args.action != "map" || args.action=="all") {

var output = "<table border='1' cellpadding='4' cellspacing='0' style='font-size:12px;' _fckstyle='font-size:12px;' _fckstyle='font-size:12px;' _fckstyle='font-size:12px;' _fckstyle='font-size:12px;' >";
let output ..= "<tr bgcolor='#dddddd'><td></td>";
if (args.pagedata == "TRUE") {
let output ..= "<td>Autore (1)</td>";
let output ..= "<td>Data modifica (2)</td>";
}
var ptemplate = wiki.page(args.templatename);
foreach (var i in fields) {
let output ..= "" .. xml.text(ptemplate,'//td[@class=\''..i..'\']',nil,true) .. "";
}
let output ..="</tr>";
foreach (var row in listglobal) {
let output ..="<tr>";
var t = listglobal[__count];
if (args.pagedata != "TRUE") {
let output ..= "<td bgcolor='#eeeeee'>"..web.link(t['pageuri'], 'V').."</td>";
} else {
let output ..= "<td bgcolor='#eeeeee'>"..web.link(t['pageuri'], string.replace(t['pagename'],"_"," ")).."</td>";
let output ..= "<td bgcolor='#eeeeee'>"..t['pageauthor'].."</td>";
let output ..= "<td bgcolor='#eeeeee'>"..date.format(t['pagedate'],"dd/MM/yy - HH:mm").."</td>";
}
foreach (var field in fields) {
var temp = t[field];
if (#temp > 40) {
if (string.contains(temp,"<a") && string.contains(temp,"</a") ) {
let temp = string.replace(temp,string.match(temp,"(<a[^>]*>)"),"");
let temp = string.replace(temp,string.match(temp,"(</a[^>]*>)"),"");
}
let temp = string.substr(temp,0,40).." >>> ";
}
let output ..="<td>"..temp.."</td>";
}
let output ..= "</tr>";
}
if (error == FALSE) {
web.html(output);
}
}

 


 

 

How to use

  • create a page to contain all Meetings (es: Meetings)
  • create some pages inside Meetings, insert the content template (Meeting) form the editor template button, insert data in the html table row (right column)
  • wait 2 o 3 minutes, lucene need some time to index the new pages
  • create a page where you want to list all meeting (es: MeetingsList) and call the aggregate template script with some parameters. Insert this Dekiscript code
  • {{template("XsysTableData",{templatename:"Template:Meeting",path:'Meetings/*',table_key:"tpl_meeting", pagedata:"TRUE",limit:"10",order:"-title"}) }}

Example

Check out a working example 

  • http://deki.intertesto.com/Applicazioni/Progetti

Comments

Use page comment to review and give me some feedback on this script.

 

Etichette
Statistiche pagina
775 view(s), 25 edit(s), and 12510 character(s)

Commenti

E' necessario connettersi per inserire un commento.

Aggiungi file

Allegati

Nome FileDimensioneDataAggiunto da 
 aggregate_tables.png
Nessuna descrizione
12.46 kB11:41, 24 Mar 2009wikiadminAzioni