Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/office/Table2CorpusMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/office/Table2CorpusMacro.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/office/Table2CorpusMacro.groovy	(revision 2268)
@@ -0,0 +1,338 @@
+package org.txm.macro.csv
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import java.nio.charset.Charset
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.utils.*
+import javax.xml.stream.*
+import java.net.URL
+
+@Field @Option(name="inputFile", usage="CSV File", widget="File", required=false, def="file.xlsx")
+		File inputFile;
+
+@Field @Option(name="outputDirectory", usage="output directory", widget="File", required=false, def="directory")
+		File outputDirectory;
+
+@Field @Option(name="textSelector", usage="column_to_test=regexp", widget="String", required=false, def="Type de notice=Notice sommaire")
+		def textSelector;
+
+@Field @Option(name="structureSelector", usage="column_to_test=regexp", widget="String", required=false, def="Type de notice=Notice sujet")
+		def structureSelector;
+
+@Field @Option(name="textIDColumn", usage="text id column", widget="String", required=false, def="Identifiant de la notice")
+		def textIDColumn;
+
+@Field @Option(name="joinColumn", usage="jointure column, values should point to the textIDColumn values", widget="String", required=false, def="Lien notice principale")
+		def joinColumn;
+
+@Field @Option(name="textMetadataColumnList", usage="text metadata columns", widget="String", required=false, def="Identifiant de la notice,Date de diffusion,Durée,Genre,Identifiant Matériels (info.)")
+		def textMetadataColumnList;
+
+@Field @Option(name="textContentColumnList", usage="text content columns", widget="String", required=false, def="Titre propre,Résumé,Descripteurs (Aff. Lig.),Descripteurs (Aff. Col.),Séquences")
+		def textContentColumnList;
+
+@Field @Option(name="structureTag", usage="structure metadata columns", widget="String", required=false, def="div")
+		def structureTag;
+
+@Field @Option(name="structureMetadataColumnList", usage="structure metadata columns", widget="String", required=false, def="Identifiant de la notice,Date de diffusion,Durée,Genre,Identifiant Matériels (info.)")
+		def structureMetadataColumnList;
+
+@Field @Option(name="structureContentColumnList", usage="structure content columns", widget="String", required=false, def="Titre propre,Résumé,Descripteurs (Aff. Lig.),Descripteurs (Aff. Col.),Séquences")
+		def structureContentColumnList;
+
+@Field @Option(name="metadataDateColumnList", usage="metadata columns of type=Date", widget="String", required=false, def="")
+		def metadataDateColumnList;
+@Field @Option(name="prefixContentColumnList", usage="metadata columns of type=Date", widget="String", required=false, def="")
+		def prefixContentColumnList;
+@Field @Option(name="listContentColumnList", usage="metadata columns of type=Date", widget="String", required=false, def="")
+		def listContentColumnList;
+
+
+//@Field @Option(name="structureOrderColumn", usage="structure column coding structure order", widget="String", required=false, def="Titre propre,Résumé,Descripteurs (Aff. Lig.),Descripteurs (Aff. Col.),Séquences")
+//		def structureOrderColumn;
+
+if (!ParametersDialog.open(this)) return;
+
+textMetadataColumnList = textMetadataColumnList.split(",")
+textContentColumnList = textContentColumnList.split(",")
+structureMetadataColumnList = structureMetadataColumnList.split(",")
+structureContentColumnList = structureContentColumnList.split(",")
+metadataDateColumnList = metadataDateColumnList.split(",")
+prefixContentColumnList = prefixContentColumnList.split(",")
+listContentColumnList = listContentColumnList.split(",")
+int ti = textSelector.indexOf("=")
+String p1 = textSelector.substring(0, ti)
+String p2 = textSelector.substring(ti+1)
+textSelector = [p1, p2]
+structureSelector = [structureSelector.substring(0, structureSelector.indexOf("=")), structureSelector.substring(structureSelector.indexOf("=")+1)]
+
+
+println "textIDColumn, joinColumn=$textIDColumn, $joinColumn"
+println "textMetadataColumnList columns: $textMetadataColumnList"
+println "textContentColumnList columns: $textContentColumnList"
+println "structureMetadataColumnList columns: $structureMetadataColumnList"
+println "structureContentColumnList columns: $structureContentColumnList"
+
+println "text selector="+textSelector
+println "structure selector="+structureSelector
+println "structureTag="+structureTag
+
+TableReader reader = new TableReader(inputFile);
+if (!reader.readHeaders()) {
+	println "Error: no header"
+	return
+}
+def headers = Arrays.asList(reader.getHeaders())
+println "table columns: $headers"
+
+def ok = true
+for (def list : ["selection":[textIDColumn, joinColumn], "textMetadataColumnList":textMetadataColumnList,
+	"textContentColumnList":textContentColumnList, "structureMetadataColumnList":structureMetadataColumnList,
+	"structureContentColumnList":structureContentColumnList]) {
+	for (String m : list.value) {
+		m = m.trim()
+		if (!headers.contains(m)) {
+			println "Error: missing ${list.key} column: $m"
+			ok = false
+		}
+	}
+}
+if (!ok) { return; }
+
+// group by text
+def texts = new LinkedHashMap()
+def nRecord = 0
+while (reader.readRecord()) {
+	nRecord++
+	//println "record="+reader.getRecord().get(textSelector[0])+" "+reader.getRecord().get(structureSelector[0])
+
+	String id = reader.get(textIDColumn).trim()
+	String join = reader.get(joinColumn).trim()
+	String textSelectorValue = reader.get(textSelector[0]).trim()
+	String structureSelectorValue = reader.get(structureSelector[0]).trim()
+	if (textSelectorValue != null && textSelectorValue.matches(textSelector[1])) {
+		if (!texts.containsKey(id)) texts[id] = []
+		texts[id].add(0, reader.getRecord())
+	} else if (structureSelectorValue != null && structureSelectorValue.matches(structureSelector[1])) {
+		if (!texts.containsKey(join)) texts[join] = []
+		texts[join].add(reader.getRecord())
+	} else {
+		// ignore
+	}
+}
+println "N lines: "+nRecord
+println "N groups: "+texts.size()
+if (texts.size()  == 0) {
+	println "No text found. Aborting."
+	return
+}
+outputDirectory.mkdir()
+
+for (def id : texts.keySet()) {
+	def toWrite = texts[id]
+	def text = toWrite[0]
+	String textSelectorValue = text.get(textSelector[0]).trim()
+	if (textSelectorValue != null && textSelectorValue.matches(textSelector[1])) {
+		println "Processing text: $id"
+
+		File outputfile = new File(outputDirectory, id+".xml")
+		XMLOutputFactory factory = XMLOutputFactory.newInstance()
+		FileOutputStream output = new FileOutputStream(outputfile)
+		XMLStreamWriter writer = factory.createXMLStreamWriter(output, "UTF-8")
+
+		writer.writeStartDocument("UTF-8","1.0")
+		writer.writeCharacters("\n") // simple XML formating
+		writer.writeStartElement("TEI")
+		writer.writeCharacters("\n") // simple XML formating
+		writer.writeStartElement("teiHeader")
+		writer.writeEndElement() // teiHeader
+		writer.writeCharacters("\n") // simple XML formating
+		writer.writeStartElement("text")
+		writer.writeAttribute("id", id)
+
+		for (String att : textMetadataColumnList) {
+			if (att in metadataDateColumnList) {
+				writeMetadataDate(text, att, writer)
+			} else {
+				writer.writeAttribute(AsciiUtils.buildAttributeId(att), text.get(att)) // struct
+			}
+		}
+
+		writer.writeCharacters("\n") // simple XML formating
+
+		writer.writeStartElement("metadata")
+		writer.writeStartElement("list")
+		writer.writeAttribute("type", "unordered")
+		writer.writeCharacters("\n")
+		textMetadataColumnList.each { att ->
+			writer.writeStartElement("item")
+			writer.writeCharacters(att+" : "+text.get(att).replaceAll("\n", ";"))
+			writer.writeEndElement() // item
+			writer.writeCharacters("\n")
+		}
+		writer.writeEndElement() // list
+		writer.writeEndElement() // metadata
+		writer.writeCharacters("\n")
+
+		for (String att : textContentColumnList) {
+			if (att in prefixContentColumnList) {
+				writeContentPrefix(text, att, writer)
+			} else if (att in listContentColumnList) {
+				writeContentList(text, att, writer)
+			} else {
+				writer.writeStartElement("p");
+				writer.writeAttribute("type", att.trim())
+				writer.writeCharacters("\n") // simple XML formating
+
+				writer.writeStartElement("head")
+				writer.writeStartElement("hi")
+				writer.writeCharacters(att+" : ")
+				writer.writeEndElement() // hi
+				writer.writeEndElement() // head
+
+				writer.writeCharacters(text.get(att)) // get textColumnList content
+				writer.writeEndElement() // t
+				writer.writeCharacters("\n") // simple XML formating)
+			}
+		}
+
+		int pb_n = 1;
+		for (int i = 1 ; i < toWrite.size() ; i++) {
+			def record = toWrite[i]
+
+			writer.writeEmptyElement("pb") // <pb/>
+			writer.writeAttribute("n", ""+pb_n++)
+
+			writer.writeStartElement(structureTag)
+
+			for (String att : structureMetadataColumnList) {
+				if (att in metadataDateColumnList) {
+					writeMetadataDate(record, att, writer)
+				} else {
+					writer.writeAttribute(AsciiUtils.buildAttributeId(att), record.get(att)) // struct
+				}
+			}
+			writer.writeCharacters("\n")
+
+			writer.writeStartElement("metadata")
+			writer.writeStartElement("list")
+			writer.writeAttribute("type", "unordered")
+			writer.writeCharacters("\n")
+			structureMetadataColumnList.each { att ->
+				writer.writeStartElement("item")
+				writer.writeCharacters(att+" : "+record.get(att).replaceAll("\n", ";"))
+				writer.writeEndElement() // item
+				writer.writeCharacters("\n")
+			}
+			writer.writeEndElement() // list
+			writer.writeEndElement() // metadata
+			writer.writeCharacters("\n")
+
+			for (String att : structureContentColumnList) {
+				if (att in prefixContentColumnList) {
+					writeContentPrefix(text, att, writer)
+				} else if (att in listContentColumnList) {
+					writeContentList(text, att, writer)
+				} else {
+					writer.writeStartElement("p");
+					writer.writeAttribute("type", att.trim())
+					writer.writeAttribute("id", record.get(textIDColumn))
+					writer.writeCharacters("\n") // simple XML formating
+
+					writer.writeStartElement("head")
+					writer.writeStartElement("hi")
+					writer.writeCharacters(att+" : ")
+					writer.writeEndElement() // hi
+					writer.writeEndElement() // head
+
+					writer.writeCharacters(record.get(att)) // get textColumnList content
+					writer.writeEndElement() // t
+					writer.writeCharacters("\n") // simple XML formating
+				}
+			}
+
+			writer.writeEndElement() // struct
+			writer.writeCharacters("\n") // simple XML formating
+		}
+
+		writer.writeEndElement() // text
+		writer.writeCharacters("\n") // simple XML formating
+		writer.writeEndElement() // TEI
+		writer.close()
+		output.close()
+		reader.close()
+	} else {
+		// error
+		println "ERROR: '$id' text group with  no text line"
+	}
+}
+
+def writeContentList(def record, def att, def writer) {
+	writer.writeCharacters("\n")
+	found = false
+	def value = record.get(att)
+	value.findAll( /(?s)([^\n]+?)[\n]/ ).each { desc ->
+		found = true
+		writer.writeCharacters("\t")
+		writer.writeStartElement("p")
+		writer.writeAttribute("rend", "list")
+		matches = (desc =~ /(?s)([^\n]+?)[\n]/)
+		writer.writeCharacters(matches[0][1])
+		writer.writeEndElement() // p
+		writer.writeCharacters("\n")
+	}
+	if (!found) {
+		writer.writeCharacters("\t")
+		writer.writeStartElement("p")
+		writer.writeAttribute("rend", "no-list")
+		writer.writeCharacters(value)
+		writer.writeEndElement() // p
+		writer.writeCharacters("\n")
+	}
+}
+
+def writeContentPrefix(def record, def att, def writer) {
+	writer.writeCharacters("\n")
+	writer.writeStartElement("list")
+	writer.writeAttribute("rend", "prefixes")
+	writer.writeAttribute("type", "unordered")
+	writer.writeCharacters("\n")
+	found = false
+	def value = record.get(att)
+	value.findAll( /(?s)[A-Z]{3}:? *([^;\n]+?) +[;\n]/ ).each { desc ->
+		found = true
+		writer.writeCharacters("\t")
+		writer.writeStartElement("item")
+		matches = (desc =~ /(?s)([A-Z]{3}):? *([^;\n]+?) +[;\n]/)
+		writer.writeAttribute("type", matches[0][1])
+		writer.writeStartElement("span")
+		writer.writeCharacters(matches[0][1]+" ")
+		writer.writeEndElement() // span
+		writer.writeCharacters(matches[0][2])
+		writer.writeEndElement() // item
+		writer.writeCharacters("\n")
+	}
+	if (!found) {
+		writer.writeCharacters(value)
+	}
+	writer.writeEndElement() // list
+	writer.writeCharacters("\n")
+}
+
+def writeMetadataDate(def record, def att, def writer) {
+	String value = record.get(att)
+	String att_normalized = AsciiUtils.buildAttributeId(att)
+	matches = (value =~ /([0-9]{2})\/([0-9]{2})\/([0-9]{4})/)
+	writer.writeAttribute(att_normalized+"jour", matches[0][1])
+	writer.writeAttribute(att_normalized+"joursemaine", new java.text.SimpleDateFormat('EEEE').format(Date.parse("dd/MM/yyyy", value)))
+	writer.writeAttribute(att_normalized+"mois", matches[0][2])
+	writer.writeAttribute(att_normalized+"annee", matches[0][3])
+	writer.writeAttribute(att_normalized+"tri", matches[0][3]+"-"+matches[0][2]+"-"+matches[0][1])
+}
+
+/*
+ String name = inputFile.getName()
+ int idx = name.lastIndexOf(".")
+ if (idx > 0) name = name.substring(0, idx)
+ */
\ No newline at end of file
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/pager.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/pager.groovy	(revision 2267)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/pager.groovy	(revision 2268)
@@ -44,81 +44,81 @@
  *  
  */
 class pager {
-
+	
 	boolean SIMPLE_TOOLTIP = false; // show less properties in word tooltips
 	String ENQ_HIGHLIGHT_ELEMENT = "b"
-
+	
 	List<String> NoSpaceBefore;
-
+	
 	/** The No space after. */
 	List<String> NoSpaceAfter;
-
+	
 	/** The pages. */
 	def pages = [];
 	def indexes = [];
-
+	
 	/** The wordcount. */
 	int wordcount = 0;
-
+	
 	/** The pagecount. */
 	int pagecount = 0;
-
+	
 	/** The wordmax. */
 	int wordmax = 10;
-
+	
 	/** The wordid. */
 	String wordid;
-
+	
 	/** The first word. */
 	boolean firstWord = true;
-
+	
 	/** The wordvalue. */
 	String wordvalue;
-
+	
 	/** The interpvalue. */
 	String interpvalue;
-
+	
 	/** The lastword. */
 	String lastword = " ";
-
+	
 	/** The wordtype. */
 	String wordtype;
-
+	
 	/** The flagform. */
 	boolean flagform = false;
-
+	
 	/** The flaginterp. */
 	boolean flaginterp = false;
-
+	
 	boolean flagcomment = false;
-
+	
 	/** The url. */
 	private def url;
-
+	
 	/** The input data. */
 	private def inputData;
-
+	
 	/** The factory. */
 	private def factory;
-
+	
 	/** The parser. */
 	private XMLStreamReader parser;
-
+	
 	/** The writer. */
 	XMLStreamWriter writer;
 	BufferedOutputStream output;
-
+	
 	File txmfile;
-
+	
 	File outfile;
-
+	
 	String corpusname ="";
 	String cuttingTag = "pb"
 	String txtname;
 	File htmlDir;
 	File defaultDir;
 	Metadatas metadatas;
-
+	
 	def interviewers = [];
 	def eventTranslations = ["^^":"mot inconnu", "?":"orthographe incertaine",
 		"()":"rupture de syntaxe", "b":"bruit indéterminé",
@@ -160,17 +160,17 @@
 		this.txmfile = txmfile;
 		this.htmlDir = htmlDir;
 		this.txtname = txtname;
-
+		
 		inputData = url.openStream();
 		factory = XMLInputFactory.newInstance();
 		parser = factory.createXMLStreamReader(inputData);
-
+		
 		defaultDir = new File(htmlDir, "default")
 		defaultDir.mkdir()
 		new File(htmlDir, "onepage").mkdir()
 		outfile = new File(htmlDir, "onepage/${txtname}.html");
 		createOutput(outfile)
-
+		
 		try {
 			process();
 		} catch(Exception e) {
@@ -181,7 +181,7 @@
 			}
 		}
 	}
-
+	
 	/**
 	 * Creates the output.
 	 *
@@ -194,14 +194,14 @@
 			XMLOutputFactory outfactory = XMLOutputFactory.newInstance();
 			output = new BufferedOutputStream(new FileOutputStream(outfile))
 			writer = outfactory.createXMLStreamWriter(output, "UTF-8");//create a new file
-
+			
 			return true;
 		} catch (Exception e) {
 			System.out.println(e.getLocalizedMessage());
 			return false;
 		}
 	}
-
+	
 	/** The events. */
 	List<String> events = [];
 	String previousEvent = "", nextEvent = "";
@@ -209,7 +209,7 @@
 	 * Process.
 	 */
 	void process() {
-
+		
 		String previousElem = "";
 		boolean parolesRaportees = false;
 		boolean firstWord = true;
@@ -221,7 +221,7 @@
 		ArrayList<String> whos = [];
 		HashMap<String, String> speakers = new HashMap<String, String>();
 		HashMap<String, String> topics = new HashMap<String, String>();
-
+		
 		writer.writeStartDocument("UTF-8","1.0");
 		writer.writeStartElement("html");
 		//<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
@@ -231,7 +231,7 @@
 		writer.writeAttribute("charset", "UTF-8");
 		writer.writeEndElement();
 		writer.writeStartElement("head");
-
+		
 		//<link rel="stylesheet" type="text/css" href="class.css" />
 		writer.writeStartElement("link");
 		writer.writeAttribute("rel", "stylesheet");
@@ -239,38 +239,67 @@
 		writer.writeAttribute("href", "transcriber.css");
 		writer.writeEndElement();
 		writer.writeEndElement();
-
+		
 		nbBreak++
 		writer.writeStartElement("body");
+		writer.writeAttribute("class", "txmeditionpage")
 		writer.writeEmptyElement("pb");
 		writer.writeAttribute("id", ""+nbBreak);
 		pages << new File(defaultDir, "${txtname}_${nbBreak}.html")
-
+		
 		for (int event = parser.next(); event != XMLStreamConstants.END_DOCUMENT; event = parser.next()) {
 			switch (event) {
 				case XMLStreamConstants.START_ELEMENT:
 					localname = parser.getLocalName();
 					switch (localname) {
 						case "text":
+						
 							writer.writeStartElement("h2");
-							writer.writeAttribute("class","titre");
+							writer.writeAttribute("class","title");
 							String title = parser.getAttributeValue(null, "title");
+						
 							if (title != null) {
 								writer.writeCharacters(title);
 							} else {
 								writer.writeCharacters("Transcription "+txmfile.getName().substring(0, txmfile.getName().length() - 4));
 							}
-							writer.writeEndElement();
-							if(metadatas != null) {
+						
+							writer.writeEmptyElement("br");
+							writer.writeStartElement("a");
+							writer.writeAttribute("onclick", "txmcommand('id', 'org.txm.backtomedia.commands.function.BackToMedia', 'corpus', '"+corpusname+"', 'text', '"+txtname+"', 'time', '0.0')");
+							writer.writeAttribute("style", "cursor: pointer;")
+							writer.writeAttribute("class", "play-media")
+							writer.writeCharacters(" ♪♪");
+							writer.writeEndElement(); // a
+						
+							writer.writeEndElement(); // h2
+						
+							String subtitle = parser.getAttributeValue(null, "subtitle");
+							if (subtitle != null && subtitle.length() > 0) {
+								writer.writeStartElement("h3");
+								writer.writeAttribute("class", "subtitle");
+								writer.writeCharacters(subtitle);
+								writer.writeEndElement(); // h3
+							}
+						
+//							println "metadatas != null: "+(metadatas != null)
+//							if (metadatas != null) {
 								writer.writeStartElement("table");
 								boolean grey = false;
-								for (String name : metadatas.getPropertyNames()) {
-									if ("title" == name) continue; // ignore "title" metadata
+								for (int i = 0 ; i < parser.getAttributeCount() ; i++) {
+									String name = parser.getAttributeName(i);
+									String value = parser.getAttributeValue(i);
+									
+									if ("title" == name) {
+										continue; // ignore "title" metadata
+									}
+									
 									grey = !grey;
 									writer.writeStartElement("tr");
-									if (grey)
+									if (grey) {
 										writer.writeAttribute("style","background-color:lightgrey;")
-									String value = parser.getAttributeValue(null, name);
+									}
+									
 									if (value != null) {
 										writer.writeStartElement("td");
 										writer.writeCharacters(name);
@@ -286,7 +315,7 @@
 									writer.writeEndElement();
 								}
 								writer.writeEndElement();
-							}
+//							}
 							break;
 						case "Topics":
 						/*writer.writeStartElement("h2");
@@ -347,44 +376,73 @@
 							flagcomment = true;
 							break;
 						case "div":
-							writer.writeStartElement("div");
-							writer.writeAttribute("class", "section");
-							String type = parser.getAttributeValue(null,"type");
-							String desc = parser.getAttributeValue(null,"topic");
-							String metadata = parser.getAttributeValue(null,"metadata");
+						
+							nbBreak++
+							writer.writeEmptyElement("pb");
+							writer.writeAttribute("id", ""+nbBreak);
+							writer.writeCharacters("\n");
+						
+							pages << new File(defaultDir, "${txtname}_${nbBreak}.html")
+							indexes << wordid
+						
+							wordcount = 0;
+							shouldBreak = false;
+						
+							writer.writeStartElement("div")
+							writer.writeAttribute("class", "section")
+						
+							String type = parser.getAttributeValue(null, "type")
+							writer.writeAttribute("type", ""+type)
+							String desc = parser.getAttributeValue(null, "topic")
+						
 							if (type != null || desc != null) {
-								writer.writeStartElement("h3");
-								if (type != null || type.length() ==0) {
+								writer.writeStartElement("h2");
+								writer.writeAttribute("class", "section-title")
+								if (type != null || type.length() == 0) {
 									writer.writeCharacters(type+": "+desc);
 								} else {
-									writer.writeCharacters(desc);
+									writer.writeCharacters(desc)
 								}
-								writer.writeEndElement(); // h3
 								
-								if (metadata != null && metadata.length() > 0) { // the metadata to show
-									writer.writeStartElement("ul");
-									for (def m : metadata.split("\t")) {
-										writer.writeStartElement("li");
-										writer.writeCharacters(m);
-										writer.writeEndElement(); // li
+								if (parser.getAttributeValue(null,"startTime") != null) {
+									writer.writeEmptyElement("br");
+									writer.writeStartElement("a")
+									writer.writeAttribute("onclick", "txmcommand('id', 'org.txm.backtomedia.commands.function.BackToMedia', 'corpus', '"+corpusname+"', 'text', '"+txtname+"', 'time', '"+parser.getAttributeValue(null,"startTime")+"')");
+									writer.writeAttribute("style", "cursor: pointer;")
+									writer.writeAttribute("class", "play-media")
+									writer.writeCharacters(" ♪♪")
+									writer.writeEndElement() // a
+								}
+								
+								writer.writeEndElement(); // h2
+							}
+						
+							String metadata = parser.getAttributeValue(null, "metadata")
+							if (metadata != null && metadata.length() > 0) { // the metadata to show
+								writer.writeStartElement("ul")
+								//println "metadata=$metadata"
+								for (def m : metadata.split("<li>")) {
+									writer.writeStartElement("li")
+									writer.writeCharacters(m)
+									writer.writeEndElement() // li
+								}
+								writer.writeEndElement() // ul
+							} else if (parser.getAttributeCount() > 1) { // process all attributes
+								writer.writeStartElement("ul")
+								for (int i = 0 ; i < parser.getAttributeCount() ; i++) {
+									String name = parser.getAttributeLocalName(i)
+									if (!"type".equals(name)
+									&& !"topic".equals(name)
+									&& !"startTime".equals(name)
+									&& !"endTime".equals(name)) {
+										writer.writeStartElement("li")
+										writer.writeCharacters(""+name+": "+parser.getAttributeValue(i))
+										writer.writeEndElement() // li
 									}
-									writer.writeEndElement(); // ul
-								} else if (parser.getAttributeCount() > 1) { // process all attributes
-									writer.writeStartElement("ul");
-									for (int i = 0 ; i < parser.getAttributeCount() ; i++) {
-										String name = parser.getAttributeLocalName(i);
-										if (!"type".equals(name)
-										&& !"topic".equals(name)
-										&& !"startTime".equals(name)
-										&& !"endTime".equals(name)) {
-											writer.writeStartElement("li");
-											writer.writeCharacters(""+name+": "+parser.getAttributeValue(i));
-											writer.writeEndElement(); // li
-										}
-									}
-									writer.writeEndElement(); // ul
 								}
+								writer.writeEndElement(); // ul
 							}
+						
 							break;
 						case "sp":
 							endBoldIfNeeded()
@@ -392,26 +450,27 @@
 							firstWho = true;
 							spokenTurn = false;
 							overlapping = false
-
+						
 							writer.writeStartElement("p");
 							writer.writeAttribute("class", "turn");
-
+						
 							overlapping = ("true" == parser.getAttributeValue(null,"overlap"))
 							String spid = parser.getAttributeValue(null,"speaker");
+						
 							whos = []
 							if (overlapping) {
 								writer.writeEmptyElement("br");
 								writeSpeaker(parser.getAttributeValue(null,"speaker"), false)
-
+								
 								writer.writeEmptyElement("br");
 								whos = spid.split(" ")
 							}
-
+						
 							break;
 						case "u":
 							writer.writeCharacters("\n");
 							this.currentTime = parser.getAttributeValue(null,"time");
-
+						
 							if (previousElem == "u" && writenLength == 0) { // if previous u had no words, it was a silence
 								writer.writeStartElement("span");
 								writer.writeAttribute("class", "event");
@@ -419,7 +478,7 @@
 								writer.writeEndElement(); // span
 								writer.writeEmptyElement("br");
 							}
-
+						
 							String spk = parser.getAttributeValue(null, "spk")
 							if (spk != null && spk != previousSPK) {
 								endBoldIfNeeded()
@@ -427,16 +486,16 @@
 								writeSpeaker(parser.getAttributeValue(null, "spk"), overlapping)
 								startBoldIfNeeded()
 							}
-
+						
 							writeCurrentTime()
 							previousSPK = spk
-
+						
 						//							writenLength = 0;
 						/*writer.writeStartElement("span");
 					 writer.writeAttribute("class", "sync");
 					 writer.writeCharacters("["+parser.getAttributeValue(null,"time")+"]");
 					 writer.writeEndElement();*/
-
+						
 							break;
 						case "event":
 							spokenTurn = true;
@@ -458,7 +517,7 @@
 										events.remove(events.size()-1)
 								}
 								else if (parser.getAttributeValue(null, "extent") == "begin") 	{
-
+									
 									writer.writeCharacters(" ["+desc+"> ");
 									events.add(desc)
 								}
@@ -484,21 +543,21 @@
 									wordid = (parser.getAttributeValue(i));
 									break;
 								}
-
+						
 							wordcount++;
 							if (wordcount >= wordmax) {
 								shouldBreak = true;
 							}
-
+						
 							if (firstWord) {
 								indexes << wordid
 								firstWord = false;
 							}
-
+						
 							break;
-
+						
 						case "ana":
-
+						
 							String type = parser.getAttributeValue(null,"type").substring(1);
 							if (SIMPLE_TOOLTIP) {
 								if (type.contains("lemma") || type.contains("pos")) {
@@ -510,7 +569,7 @@
 								interpvalue+=", "+type+"="
 							}
 							break;
-
+						
 						case "form":
 							wordvalue="";
 							interpvalue ="";
@@ -536,10 +595,10 @@
 							break;
 						case "Speaker":
 							break;
-
+						
 						case "div":
 						//writer.writeCharacters("}");
-
+						
 							writer.writeEndElement(); // div
 							writer.writeCharacters("\n");
 							break;
@@ -553,18 +612,18 @@
 								writer.writeEndElement();
 								writer.writeEmptyElement("br");
 							}
-
+						
 							writer.writeEndElement(); // p
-
+						
 							if (shouldBreak) {
 								nbBreak++
 								writer.writeEmptyElement("pb");
 								writer.writeAttribute("id", ""+nbBreak);
 								writer.writeCharacters("\n");
-
+								
 								pages << new File(defaultDir, "${txtname}_${nbBreak}.html")
 								indexes << wordid
-
+								
 								wordcount = 0;
 								shouldBreak = false;
 							}
@@ -590,12 +649,12 @@
 							String endOfLastWord = "";
 							if(l > 0)
 								endOfLastWord = lastword.subSequence(l-1, l);
-
+						
 							if(interpvalue != null)
 								interpvalue = interpvalue.replace("\"","&quot;");
 							if(events.size() > 0)
 								interpvalue = interpvalue.replace("event=", "event="+events.toString().replace("\"","&quot;")); // remove ", "
-
+						
 							if(nextEvent.length() > 0)
 							{
 								interpvalue = interpvalue.replace("event=", "event="+nextEvent+", ")
@@ -617,7 +676,7 @@
 								//								println " SPACE"
 								writer.writeCharacters(" ");
 							}
-
+						
 							if (interpvalue.contains("rapp1")) {
 								writer.writeCharacters(" «");
 							} else if (wordvalue == "\"") {
@@ -642,17 +701,17 @@
 								writer.writeCharacters("_[!]");
 								writer.writeEndElement();
 							}
-
+						
 							if (interpvalue.contains("rapp2")) {
 								writer.writeCharacters(" » ");
 							}
-
+						
 							lastword=wordvalue;
 							break;
 					}
-
+				
 					break;
-
+				
 				case XMLStreamConstants.CHARACTERS:
 					if(flagform)
 						if(parser.getText().length() > 0)
@@ -664,17 +723,17 @@
 			}
 		}
 		writer.writeEndElement();
-
+		
 		writer.writeEmptyElement("pb");
 		nbBreak++
 		writer.writeAttribute("id", ""+nbBreak);
-
+		
 		writer.writeEndElement();
 		writer.close();
 		output.close();
 		if (parser != null) parser.close();
 		if (inputData != null) inputData.close();
-
+		
 		File txmhome = new File(org.txm.Toolbox.getTxmHomePath());
 		File xlsDir  = new File(txmhome, "xsl");
 		File xslfile = new File(xlsDir,"breakByMilestone.xsl");
@@ -685,13 +744,13 @@
 		//		println "html: "+outfile
 		//		println "pages: "+pages
 		//		println "words: "+indexes
-
-
+		
+		
 		if (pages.size() > 1) {
 			for (int i = 1 ; i < nbBreak ; i++) {
 				ApplyXsl2 a = new ApplyXsl2(xslfile.getAbsolutePath());
-				String[] params = ["pbval1", i,"pbval2", i+1];
-
+				String[] params = ["pbval1", i, "pbval2", i+1];
+				
 				File resultfile = pages[i-1]
 				//println "BBmilestones: "+i+" "+(i+1)+" in file "+resultfile
 				//println "process $outfile -> $resultfile"
@@ -702,17 +761,24 @@
 			FileCopy.copy(outfile, page)
 		}
 	}
-
-	private void writeCurrentTime()
-	{
+	
+	private void writeCurrentTime() {
 		writer.writeStartElement("span");
 		writer.writeAttribute("class", "sync");
 		writer.writeCharacters(currentTime);
+		
+		writer.writeStartElement("a");
+		writer.writeAttribute("onclick", "txmcommand('id', 'org.txm.backtomedia.commands.function.BackToMedia', 'corpus', '"+corpusname+"', 'text', '"+txtname+"', 'time', '"+currentTime+"')");
+		writer.writeAttribute("style", "cursor: pointer;")
+		writer.writeAttribute("class", "play-media")
+		writer.writeCharacters(" ♪♪");
+		writer.writeEndElement(); // a
+		
 		writer.writeEndElement();
 	}
-
+	
 	private void writeSpeaker(String spk, boolean overlapping) {
-
+		
 		writer.writeStartElement("span");
 		writer.writeAttribute("class", "spk");
 		if(interviewers.contains(spk))
@@ -721,17 +787,19 @@
 			bold = false;
 		spk = spk.replaceAll('^([^0-9]*)([0-9]+)$', '$1 $2');
 		if (overlapping) writer.writeCharacters("// ")
+		
 		writer.writeCharacters(spk+": ")
+		
 		writer.writeEndElement(); // span@class=spk
 	}
-
+	
 	private String translateEvent(String desc) {
 		if(eventTranslations.containsKey(desc))
 			return eventTranslations.get(desc);
 		else
 			return desc;
 	}
-
+	
 	boolean boldOpenned = false;
 	private void startBoldIfNeeded() {
 		if (bold) {
@@ -739,7 +807,7 @@
 			boldOpenned = true;
 		}
 	}
-
+	
 	private endBoldIfNeeded() {
 		if (boldOpenned) {
 			//			println "CLOSE BOLD"
@@ -747,7 +815,7 @@
 			boldOpenned = false;
 		}
 	}
-
+	
 	//	private String formatTime(float time, boolean doshort)
 	//	{
 	//		String rez = " ";
@@ -787,7 +855,7 @@
 	//		//		}
 	//		return rez;
 	//	}
-
+	
 	/**
 	 * Gets the page files.
 	 *
@@ -796,7 +864,7 @@
 	public ArrayList<File> getPageFiles() {
 		return pages;
 	}
-
+	
 	/**
 	 * Gets the idx.
 	 *
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy	(revision 2267)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/AddSections.groovy	(revision 2268)
@@ -10,7 +10,7 @@
 File trsDirectory = new File("/home/mdecorde/TEMP/ANTRACT/AF/trs")
 def idTRSColumn = "Lien notice principale"
 def typeColumns = ["Identifiant de la notice"]
-def topicColumns = ["Titre propre", "Genre", "antract_debut", "antract_fin"]
+def topicColumns = ["Titre propre", "Notes du titre"]
 def startTimeColumn = "antract_debut"
 def endTimeColumn = "antract_fin"
 //def metadataColumns = ["Identifiant de la notice", "Titre propre", "antract_debut", "antract_fin"]
@@ -21,7 +21,7 @@
 	return
 }
 
-
+println "Loading data from $metadataFile..."
 CsvReader reader = new CsvReader(metadataFile.getAbsolutePath(), "\t".charAt(0), Charset.forName("UTF-8"))
 reader.readHeaders()
 def header = reader.getHeaders()
@@ -80,6 +80,7 @@
 	}
 
 def sectionGroupsToInsert = [:]
+println "Reading data..."
 while (reader.readRecord()) {
 	String id = reader.get(idTRSColumn).trim()
 	if (id.endsWith(".mp4")) id = id.substring(0, id.length()-4)
@@ -95,7 +96,7 @@
 		
 		def m = [:]
 		
-		for (def todo : ["metadata":metadataColumns, "topic":topicColumns, "type":typeColumns]) {
+		for (def todo : ["topic":topicColumns, "type":typeColumns]) {
 			def data = []
 			for (def col : todo.value) {
 				if (reader.get(col).trim().length() > 0) {
@@ -104,6 +105,9 @@
 			}
 			m[todo.key] = data.join("\t")
 		}
+		for (def col : metadataColumns) {
+			m[AsciiUtils.buildAttributeId(col)] = reader.get(col)
+		}
 		
 		m["startTime"] = strTotime(reader.get(startTimeColumn))
 		m["endTime"] = strTotime(reader.get(endTimeColumn))
@@ -113,7 +117,7 @@
 	}
 }
 
-println "N sections: "+sectionGroupsToInsert.size()
+println "Inserting sections... "+sectionGroupsToInsert.size()
 
 ConsoleProgressBar cpb = new ConsoleProgressBar(sectionGroupsToInsert.keySet().size())
 for (String id : sectionGroupsToInsert.keySet()) {
@@ -181,7 +185,6 @@
 				
 				currentSection = found
 				currentNode = new Node(trsEpisode, "Section", currentSection[2])
-				//trsEpisode.appendNode(currentNode)
 			}
 		}
 		trsSection.remove(turn)
@@ -201,3 +204,4 @@
 	}
 }
 cpb.done()
+println "Done."
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/importer.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/importer.groovy	(revision 2267)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/importer.groovy	(revision 2268)
@@ -176,6 +176,7 @@
 		//TOKENIZE
 		println "Tokenizing "+files.length+" files from $txmDir"
 		File tokenizedDir = new File(binDir, "tokenized")
+		tokenizedDir.deleteDir()
 		tokenizedDir.mkdir()
 		cpb = new ConsoleProgressBar(files.length)
 		for (File pfile : files) {
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/transcriberLoader.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/transcriberLoader.groovy	(revision 2267)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/transcriber/transcriberLoader.groovy	(revision 2268)
@@ -112,8 +112,9 @@
 			Toolbox.getMetadataColumnSeparator(),
 			Toolbox.getMetadataTextSeparator(), 1)
 }
-else
+else {
 	println "no metadata file: "+allMetadataFile
+}
 
 File propertyFile = new File(srcDir, "import.properties")//default
 Properties props = new Properties();
@@ -289,10 +290,11 @@
 		cpb.done()
 
 		//copy transcriber.css
-		File cssfile = new File(Toolbox.getTxmHomePath(), "css/transcriber.css")
+		File cssfile = new File(Toolbox.getTxmHomePath(), "css/transcriber.css")
+		File cssTXMFile = new File(Toolbox.getTxmHomePath(), "css/txm.css")
 		if (cssfile.exists() && htmlDir.exists()) {
-			FileCopy.copy(cssfile, new File(htmlDir, "transcriber.css"));
-			FileCopy.copy(cssfile, new File(htmlDir, "onepage/transcriber.css"));
+			FileCopy.copy(cssfile, new File(htmlDir, "onepage/transcriber.css"));
+			FileCopy.copy(cssfile, new File(htmlDir, "default/txm.css"));
 			FileCopy.copy(cssfile, new File(htmlDir, "default/transcriber.css"));
 		}
 		
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xtz/XTZDefaultPagerStep.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xtz/XTZDefaultPagerStep.groovy	(revision 2267)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xtz/XTZDefaultPagerStep.groovy	(revision 2268)
@@ -323,6 +323,7 @@
 
 						rend = getAttributeValue(parser, null, "rend")
 						if (rend == null) rend = "";
+						
 						switch (localname) {
 							case "text":
 								LinkedHashMap attributes = new LinkedHashMap();
