Index: jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java diff -u jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.2 --- jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.1.1.1 Mon Oct 30 19:34:05 2006 +++ jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java Fri Nov 3 14:42:08 2006 @@ -23,9 +23,9 @@ * Created: 30 oct. 06 00:14:18 * * @author poussin - * @version $Revision: 1.1.1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2006/10/30 19:34:05 $ + * Last update: $Date: 2006/11/03 14:42:08 $ * by : $Author: bpoussin $ */ @@ -73,7 +73,7 @@ static boolean DEBUG = true; - static private Log log = LogFactory.getLog(JRSTGenerator.class); + static private Log log = LogFactory.getLog(JRSTGeneratorTest.class); protected Writer out = null; protected int sectionLevel = 0; Index: jrst2/src/java/org/codelutin/jrst/JRSTLexer.java diff -u jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.2 --- jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.1.1.1 Mon Oct 30 19:34:05 2006 +++ jrst2/src/java/org/codelutin/jrst/JRSTLexer.java Fri Nov 3 14:42:08 2006 @@ -23,9 +23,9 @@ * Created: 28 oct. 06 00:44:20 * * @author poussin - * @version $Revision: 1.1.1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2006/10/30 19:34:05 $ + * Last update: $Date: 2006/11/03 14:42:08 $ * by : $Author: bpoussin $ */ @@ -40,6 +40,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.dom4j.DocumentHelper; import org.dom4j.Element; @@ -54,33 +56,50 @@ * remove alors il peut relire autant de fois qu'il veut le meme element, ou * essayer d'en lire un autre. *

- * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes - * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} - * + * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes + * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} + * * @author poussin */ public class JRSTLexer { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(JRSTLexer.class); + + static final protected String TABLE = "table"; + static final protected String ROW = "row"; + static final protected String CELL = "cell"; + + static final protected String TABLE_HEADER = "header"; + static final protected String TABLE_WIDTH = "width"; + + static final protected String ROW_END_HEADER = "endHeader"; + + static final protected String CELL_INDEX_START = "indexStart"; + static final protected String CELL_INDEX_END = "indexEnd"; + static final protected String CELL_BEGIN = "begin"; + static final protected String CELL_END = "end"; /** - * retient le niveau du titre, pour un titre de type double, on met + * retient le niveau du titre, pour un titre de type double, on met * deux fois le caratere dans la chaine, sinon on le met une seul fois. - * + * *

      * =====
      * Super
      * =====
-     * 
+     *
      * titre
      * -----
      * 
- * + * * donnera dans la liste ["==", "-"] */ private List titleLevels = null; private AdvancedReader in = null; /** length of the last element returned (number of char need to this element) */ private int elementLength = 0; - + public JRSTLexer(Reader reader) { titleLevels = new ArrayList(); this.in = new AdvancedReader(reader); @@ -98,37 +117,37 @@ in.reset(); return result; } - + /** * remove one element from list of element already read * @return - * @throws IOException + * @throws IOException */ public void remove() throws IOException { in.skip(elementLength); } - + private void beginPeek() throws IOException { elementLength = 0; in.mark(); } - + private void endPeek() throws IOException { elementLength = in.readSinceMark(); in.reset(); } - + /** * Read block text, block text have same indentation and is continu (no * blank line) - * + * * @param minLeftMargin min left blank needed to accept to read block * @return - * @throws IOException + * @throws IOException */ private String [] readBlock(int minLeftMargin) throws IOException { - String [] result = new String[0]; - String firstLine = in.readLine(); + String [] result = new String[0]; + String firstLine = in.readLine(); if (firstLine != null) { in.unread(firstLine, true); int level = level(firstLine); @@ -136,13 +155,13 @@ result = in.readWhile("^ {"+level+"}\\S+.*"); } } - + return result; } - + /** - * All lines are joined and left and right spaces are removed during join - * + * All lines are joined and left and right spaces are removed during join + * * @param lines * @return */ @@ -150,7 +169,7 @@ String result = joinBlock(lines, " ", true); return result; } - + private String joinBlock(String [] lines, String joinSep, boolean trim) { String result = ""; String sep = ""; @@ -163,7 +182,7 @@ } return result; } - + /** * Return title or para * @return @@ -176,22 +195,22 @@ } if (result == null) { result = peekBodyElement(); - } - - return result; + } + + return result; } /** * read doc info author, date, version, ... or field list element *
      * :author: Benjamin Poussin
-     * :address: 
+     * :address:
      *   Quelque part
      *   Dans le monde
      * 
- * + * * @return - * @throws IOException + * @throws IOException */ public Element peekDocInfo() throws IOException { Element result = null; @@ -200,12 +219,12 @@ } if (result == null) { result = peekFieldList(); - } - - return result; + } + + return result; } - + /** * Return para * @return @@ -233,17 +252,17 @@ } if (result == null) { result = peekLiteralBlock(); - } + } if (result == null) { result = peekPara(); - } - + } + return result; } - + public Element peekTransition() throws IOException { beginPeek(); - + Element result = null; // must have one blank line before @@ -260,52 +279,52 @@ } } } - - endPeek(); + + endPeek(); return result; } /** * read paragraph with attribut level that represente the space numbers - * at left side - * + * at left side + * * @return <paragraph level="[int]">[text]</paragraph> - * @throws IOException + * @throws IOException */ public Element peekPara() throws IOException { beginPeek(); - + Element result = null; in.skipBlankLines(); - + String [] lines = readBlock(0); - if (lines.length > 0) { + if (lines.length > 0) { int level = level(lines[0]); String para = joinBlock(lines); - + if (para.endsWith(": ::")) { para = para.substring(0, para.length() - " ::".length()); in.unread("::", true); } else if (para.endsWith("::")) { para = para.substring(0, para.length() - ":".length()); // keep one : - in.unread("::", true); + in.unread("::", true); } - + result = DocumentHelper.createElement(PARAGRAPH) .addAttribute("level", String.valueOf(level)) .addText(para); } - endPeek(); + endPeek(); return result; } public Element peekLiteralBlock() throws IOException { beginPeek(); - + Element result = null; in.skipBlankLines(); - + String [] prefix = in.readLines(2); if (prefix.length == 2 && prefix[0].matches("::\\s*") && prefix[1].matches("\\s*")) { @@ -314,24 +333,24 @@ if (para != null) { int level = level(para); para = para.substring(level) + "\n"; - - // it's literal block until level is down + + // it's literal block until level is down String [] lines = in.readWhile("^ {"+level+"}.*"); while (lines.length > 0) { for (String line : lines) { para += line.substring(level) + "\n"; - } + } in.skipBlankLines(); lines = in.readWhile("^ {"+level+"}.*"); } - + result = DocumentHelper.createElement(LITERAL_BLOCK) .addAttribute("level", String.valueOf(level)) .addText(para); } } - endPeek(); + endPeek(); return result; } @@ -339,13 +358,13 @@ * read doc info author, date, version, ... *
      * :author: Benjamin Poussin
-     * :address: 
+     * :address:
      *   Quelque part
      *   Dans le monde
      * 
- * + * * @return - * @throws IOException + * @throws IOException */ public Element peekDocInfoItem() throws IOException { beginPeek(); @@ -358,16 +377,16 @@ result = DocumentHelper.createElement(DOCINFO); result.addAttribute("level", "0"); String infotype = line.substring(1, line.indexOf(":", 1)); - + if (!in.eof()) { String [] content = readBlock(1); line += joinBlock(content); - } + } String text = line.substring(line.indexOf(":", 1) + 1).trim(); - + // CVS, RCS support text = text.replaceAll("\\$\\w+: (.+?)\\$", "$1"); - + result.addAttribute("type", infotype).addText(text); } @@ -385,42 +404,209 @@ in.skipBlankLines(); String line = in.readLine(); - if (line != null && line.matches("^\\s*(\\+-+)+\\+\\s*$")) { // complexe table - result = DocumentHelper.createElement(TABLE); - result.addAttribute("level", String.valueOf(level(line))); - - String [] table = in.readUntilBlank(); - line += "\n" + joinBlock(table, "\n", false); - - result.addText(line); - } else if (line != null && line.matches("^\\s*(=+ +)+=+\\s*$")) { // simple table - // dans les tables simples il peut y avoir des lignes blanches au - // milieu. Mais la premiere et la derniere lignes sont identiques - String first = line; - - result = DocumentHelper.createElement(TABLE); - result.addAttribute("level", String.valueOf(level(line))); - - String [] table = in.readUntil(first); - line += "\n" + joinBlock(table, "\n", false); - String next = in.readLine(); - line += "\n" + next; + if (line != null) { + Pattern pTableBegin = Pattern.compile("^\\s*(\\+-+)+\\+\\s*$"); + Matcher matcher = null; - next = in.readLine(); - if (line != null) { - if (next.matches("\\s*")) { - // no header - in.unread(next, true); - } else { - // read body table - table = in.readUntil(first); - line += "\n" + joinBlock(table, "\n", false); - next = in.readLine(); - line += "\n" + next; + matcher = pTableBegin.matcher(line); + if (matcher.matches()) { // complexe table + result = DocumentHelper.createElement(TABLE); + result.addAttribute(TABLE_HEADER, "false"); + int level = level(line); + result.addAttribute("level", String.valueOf(level)); + line = line.trim(); + int tableWidth = line.length(); + result.addAttribute(TABLE_WIDTH, String.valueOf(tableWidth)); + + Pattern pCellEnd = Pattern.compile("^\\s{"+level+"}(\\+-+\\+|\\|(?:[^+]+))([^+]+(?:\\+|\\|\\s*$)|-+\\+)*\\s*"); // fin de ligne + Pattern pCell = Pattern.compile("^\\s{"+level+"}(\\|[^|]+)+\\|\\s*$"); // une ligne + Pattern pHeader = Pattern.compile("^\\s{"+level+"}(\\+=+)+\\+\\s*$"); // fin du header + Pattern pEnd = Pattern.compile("^\\s{"+level+"}(\\+-+)+\\+\\s*$"); // fin de table + + // used to know if | is cell separator or not + String lastSeparationLine = line; + String lastLine = line; + + Element row = DocumentHelper.createElement(ROW); + String [] table = in.readUntilBlank(); + boolean done = false; + for (String l : table) { + done =false; + l = l.trim(); + if (l.length() != tableWidth) { + // Erreur dans la table, peut-etre lever une exception ? + result = null; + break; + } + matcher = pEnd.matcher(l); + if (!done && matcher.matches()) { + // fin normale de ligne, on peut directement l'assigner + lastSeparationLine = l; + for (Element cell : (List)row.elements()) { + cell.addAttribute(CELL_END, "true"); + } + row.addAttribute(ROW_END_HEADER, "false"); + result.add(row); + row = DocumentHelper.createElement(ROW); + done =true; + } + matcher = pHeader.matcher(l); + if (!done && matcher.matches()) { + // fin de du header, on peut directement l'assigner + lastSeparationLine = l; + for (Element cell : (List)row.elements()) { + cell.addAttribute(CELL_END, "true"); + } + row.addAttribute(ROW_END_HEADER, "true"); + result.add(row); + result.addAttribute(TABLE_HEADER, "true"); + row = DocumentHelper.createElement(ROW); + done =true; + } + matcher = pCell.matcher(l); + if (!done && matcher.matches()) { + //debug + row.addAttribute("debug", "pCell"); + // recuperation des textes des cellules + int start = -1; + String content = ""; + matcher = Pattern.compile("([^|]+)\\|").matcher(l); + for (int cellNumber=0; matcher.find(); cellNumber++) { + int tmpstart = matcher.start(1); + int end = matcher.end(1); + String tmpcontent = matcher.group(1); + // on a forcement un | ou un + au dessus du + + // et forcement un + sur lastSeparationLine + // sinon ca veut dire qu'il y avait un | dans la cell + if ((lastLine.charAt(end) == '|' || lastLine.charAt(end) == '+') + && lastSeparationLine.charAt(end) == '+') { + if ("".equals(content)) { + content = tmpcontent; + } + if (start == -1) { + start = tmpstart; + } + Element cell = null; + if (row.nodeCount() <= cellNumber) { + cell = row.addElement(CELL); + cell.addAttribute(CELL_END, "false"); + } else { + cell = (Element)row.node(cellNumber); + + } + cell.addAttribute(CELL_INDEX_START, String.valueOf(start)); + cell.addAttribute(CELL_INDEX_END, String.valueOf(end)); + cell.setText(cell.getText() + "\n" + content); + start = end + 1; // +1 to pass + or | at end of cell + content = ""; + } else { +// start = tmpstart; + content += tmpcontent + "|"; + } + } + done =true; + } + matcher = pCellEnd.matcher(l); + if (!done && matcher.matches()) { + //debug + row.addAttribute("debug", "pCellEnd"); + // fin d'une ligne, on ne peut pas l'assigner directement + // pour chaque continuation de cellule, il faut copier + // l'ancienne valeur + + // mais on commence tout de meme par fermer tout les cells + for (Element cell : (List)row.elements()) { + cell.addAttribute(CELL_END, "true"); + } + + StringBuffer tmp = new StringBuffer(l); + int start = -1; + String content = ""; + matcher = Pattern.compile("([^+|]+|-+)([+|])").matcher(l); + for (int cellNumber=0; matcher.find(); cellNumber++) { + int tmpstart = matcher.start(1); + int end = matcher.end(1); + String tmpcontent = matcher.group(1); + String ender = matcher.group(2); + if (!tmpcontent.matches("-+")) { + // on a forcement un | au dessus du + ou du | + // sinon ca veut dire qu'il y avait un + dans la cell + if (lastLine.charAt(end) == '|') { + if (start == -1) { + start = tmpstart; + } + // -1 and +1 to take the + or | at begin and end + String old = lastSeparationLine.substring(start -1 , end + 1); + tmp.replace(start - 1, end + 1, old); + if ("".equals(content)) { + content = tmpcontent; + } + Element cell = null; + if (row.nodeCount() <= cellNumber) { + cell = row.addElement(CELL); + } else { + cell = (Element)row.node(cellNumber); + + } + cell.setText(cell.getText() + "\n" + content); + // on a ajouter des choses dans la cell, donc + // ce n'est pas la fin + cell.addAttribute(CELL_END, "false"); + cell.addAttribute(CELL_INDEX_START, String.valueOf(start)); + cell.addAttribute(CELL_INDEX_END, String.valueOf(end)); + start = end + 1; // +1 to pass + or | at end of cell + content = ""; + } else { +// start = tmpstart; + content += tmpcontent + ender; + } + } + } + lastSeparationLine = tmp.toString(); + row.addAttribute(ROW_END_HEADER, "false"); + result.add(row); + row = DocumentHelper.createElement(ROW); + done = true; + } + if (!done) { + log.warn("Bad table format line " + in.getLineNumber()); + } + lastLine = l; } + + // + // line += "\n" + joinBlock(table, "\n", false); + // + // result.addText(line); + } else if (line.matches("^\\s*(=+ +)+=+\\s*$")) { // simple table + // dans les tables simples il peut y avoir des lignes blanches au + // milieu. Mais la premiere et la derniere lignes sont identiques + // TODO cela ne parse pas la table, il faut le faire + String first = line; + + result = DocumentHelper.createElement(LITERAL_BLOCK); + result.addAttribute("level", String.valueOf(level(line))); + + String [] table = in.readUntil(first); + line += "\n" + joinBlock(table, "\n", false); + String next = in.readLine(); + line += "\n" + next; + + next = in.readLine(); + if (line != null) { + if (next.matches("\\s*")) { + // no header + in.unread(next, true); + } else { + // read body table + table = in.readUntil(first); + line += "\n" + joinBlock(table, "\n", false); + next = in.readLine(); + line += "\n" + next; + } + } + result.addText(line); } - - result.addText(line); } endPeek(); @@ -434,9 +620,9 @@ * - first line * - next line * - * + * * @return <bullet_list level="[int]" bullet="char"><[text];</bullet_list> - * @throws IOException + * @throws IOException */ public Element peekBulletList() throws IOException { beginPeek(); @@ -451,13 +637,13 @@ result = DocumentHelper.createElement(BULLET_LIST) .addAttribute("level", String.valueOf(level)) .addAttribute("bullet", bullet); - + if (!in.eof()) { String [] content = readBlock(level + 1); line += " " + joinBlock(content); - } + } String text = line.substring(level + 1).trim(); - + result.addText(text); } @@ -473,9 +659,9 @@ * and other text * :last empty: * - * + * * @return <field_list level="[int]" name="[text]">[text]</field_list> - * @throws IOException + * @throws IOException */ public Element peekFieldList() throws IOException { beginPeek(); @@ -498,13 +684,13 @@ if (!in.eof()) { String [] content = readBlock(level + 1); line += " " + joinBlock(content); - } + } String text = line.substring(begin).trim(); result.addText(text); } } - + endPeek(); return result; } @@ -521,9 +707,9 @@ * le mot : la classe 1 : la classe 2 * la definition * - * + * * @return <definition_list level="[int]" term="[text]" classifiers="[text]">[text]</definition_list> - * @throws IOException + * @throws IOException */ public Element peekDefinitionList() throws IOException { beginPeek(); @@ -541,7 +727,7 @@ if (matcher.matches()) { String term = matcher.group(1); String classifiers = matcher.group(2); - + result = DocumentHelper.createElement(DEFINITION_LIST) .addAttribute("level", String.valueOf(level)) .addAttribute("term", term) @@ -555,14 +741,14 @@ } } } - + endPeek(); return result; } - + /** * read enumarted list - * + * * can be: *
  • 1, 2, 3, ... *
  • a, b, c, ... @@ -571,15 +757,15 @@ *
  • I, II, III, IV, ... * * or # for auto-numbered - * + * *
          * 1. next line
          * 1) next line
          * (1) first line
          * 
    - * + * * @return <enumerated_list level="[int]" start="[number]" prefix="[char]" suffix="[char]" enumtype="[(arabic|loweralpha|upperalpha|lowerroman|upperroman]">[text]</enumerated_list> - * @throws IOException + * @throws IOException */ public Element peekEnumeratedList() throws IOException { beginPeek(); @@ -596,8 +782,8 @@ String start = matcher.group(2); String suffix = matcher.group(3); int begin = matcher.end(3); - - // arabic|loweralpha|upperalpha|lowerroman|upperroman + + // arabic|loweralpha|upperalpha|lowerroman|upperroman String enumtype = "auto"; if (start.matches("\\d+")) { enumtype = "arabic"; @@ -614,7 +800,7 @@ enumtype = "upperalpha"; start = String.valueOf((int)start.charAt(0) -(int)'A'); } - + result = DocumentHelper.createElement(ENUMERATED_LIST) .addAttribute("level", String.valueOf(level)) .addAttribute("start", start) @@ -625,7 +811,7 @@ if (!in.eof()) { String [] content = readBlock(level + 1); line += " " + joinBlock(content); - } + } String text = line.substring(begin).trim(); result.addText(text); @@ -638,22 +824,22 @@ /** * Parse un titre simple ou double - * + * * simple: *
          * Le titre
          * ========
          * 
    - * + * * double: *
          * ============
          *   le titre
          * ============
          * 
    - * + * * @return <title level="[int]" type="[simple|double]" char="[underline char]"> - * @throws IOException + * @throws IOException */ public Element peekTitle() throws IOException { beginPeek(); @@ -683,12 +869,12 @@ .addText(line); } } - + if (result != null) { // add level information String titleLevel = result.attributeValue("char"); if ("double".equals(result.attributeValue("type"))) { - titleLevel += titleLevel; + titleLevel += titleLevel; } int level = titleLevels.indexOf(titleLevel); if (level == -1) { @@ -697,7 +883,7 @@ } result.addAttribute("level", String.valueOf(JRSTReader.MAX_SECTION_DEPTH + level)); } - + endPeek(); return result; } @@ -716,7 +902,7 @@ boolean result = line.matches("(["+escapeRegex(TITLE_CHAR)+"])\\1+"); return result; } - + /** * @param title_char * @return @@ -727,13 +913,13 @@ } private int level(String line) { - int result = 0; + int result = 0; while (line.length() > result && line.charAt(result) == ' ') { result++; } return result; } - + } Index: jrst2/src/java/org/codelutin/jrst/JRSTReader.java diff -u jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.2 --- jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.1.1.1 Mon Oct 30 19:34:05 2006 +++ jrst2/src/java/org/codelutin/jrst/JRSTReader.java Fri Nov 3 14:42:08 2006 @@ -23,9 +23,9 @@ * Created: 27 oct. 06 00:15:34 * * @author poussin - * @version $Revision: 1.1.1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2006/10/30 19:34:05 $ + * Last update: $Date: 2006/11/03 14:42:08 $ * by : $Author: bpoussin $ */ @@ -35,6 +35,10 @@ import java.io.IOException; import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; import java.util.regex.Matcher; import org.apache.commons.lang.ObjectUtils; @@ -159,7 +163,7 @@ *

    * On construit un arbre XML representant le RST au fur et a mesure, on peut * ensuite appliquer une fueille de style ou autre chose avec - * {@link JRSTGenerator} + * {@link JRSTGeneratorTest} * *

    * Tous les elements ont un attribut level qui permet de savoir on il est dans @@ -317,13 +321,15 @@ Element para = parent.addElement(LITERAL_BLOCK); copyLevel(item, para); para.setText(item.getText()); - } else if (itemEquals(TABLE, item)) { + } else if (itemEquals(JRSTLexer.TABLE, item)) { // TODO now we take table as LITERAL_BLOCK, but in near // futur we must parse correctly TABLE (show JRSTGenerator and JRSTLexer too) lexer.remove(); - Element para = parent.addElement(TABLE); - copyLevel(item, para); - para.setText(item.getText()); + Element table = composeTable(lexer, item); + parent.add(table); + // Element para = parent.addElement(TABLE); +// copyLevel(item, para); +// para.setText(item.getText()); } else if (itemEquals(BULLET_LIST, item)) { Element list = composeBulletList(lexer); parent.add(list); @@ -348,6 +354,104 @@ return parent; } + /** + * @param lexer + * @param item + * @return + */ + private Element composeTable(JRSTLexer lexer, Element item) throws IOException, DocumentException { + Element result = DocumentHelper.createElement(TABLE); + + int tableWidth = Integer.parseInt(item.attributeValue(JRSTLexer.TABLE_WIDTH)); + + TreeSet beginCellList = new TreeSet(); + + for (Element cell : (List)item.selectNodes(JRSTLexer.ROW+"/"+JRSTLexer.CELL)) { + Integer begin = Integer.valueOf(cell.attributeValue(JRSTLexer.CELL_INDEX_START)); + beginCellList.add(begin); + } + + int [] beginCell = new int[beginCellList.size() + 1]; // + 1 to put table width to simulate new cell + int [] lengthCell = new int[beginCellList.size()]; + + int cellNumber = 0; + for (int b : beginCellList) { + beginCell[cellNumber] = b; + if (cellNumber > 0) { + lengthCell[cellNumber - 1] = beginCell[cellNumber] - beginCell[cellNumber - 1]; + } + cellNumber++; + } + beginCell[cellNumber] = tableWidth; + lengthCell[cellNumber - 1] = beginCell[cellNumber] - beginCell[cellNumber - 1]; + + + Element tgroup = result.addElement(TGROUP).addAttribute("cols", String.valueOf(cellNumber)); + for (int width : lengthCell) { + tgroup.addElement(COLSPEC).addAttribute("colwidth", String.valueOf(width)); + } + + Element rowList = null; + if ("true".equals(item.attributeValue(JRSTLexer.TABLE_HEADER))) { + rowList = tgroup.addElement(THEAD); + } else { + rowList = tgroup.addElement(TBODY); + } + List rows = (List)item.selectNodes(JRSTLexer.ROW); + for (int r=0; r cells = (List)rows.get(r).selectNodes(JRSTLexer.CELL); + for (int c=0; c 0) { + entry.addAttribute("morerows", String.valueOf(morerows)); + } + + // on compte le nombre de cellules regroupees horizontalement + int morecols = 0; + tmpCell = cells.get(c + morecols); + int cellEnd = Integer.parseInt(tmpCell.attributeValue(JRSTLexer.CELL_INDEX_END)); + while (cellEnd + 1 != beginCell[c + morecols + 1]) { + morecols++; +// tmpCell = cells.get(c + morecols); +// cellEnd = Integer.parseInt(tmpCell.attributeValue(JRSTLexer.CELL_INDEX_END)); + } + if (morecols > 0) { + entry.addAttribute("morecols", String.valueOf(morecols)); + } + +// JRSTReader reader = new JRSTReader(); +// Document doc = reader.read(new StringReader(text)); +// entry.appendContent(doc.getRootElement()); + entry.setText(text); + } + } + if ("true".equals(rows.get(r).attributeValue(JRSTLexer.ROW_END_HEADER))) { + rowList = tgroup.addElement(TBODY); + } + } + + return result; + } + private Element composeBulletList(JRSTLexer lexer) throws IOException, DocumentException { Element item = lexer.peekBulletList(); Element result = DocumentHelper.createElement(BULLET_LIST);