com.hfg.xml.msofficexml.docx.wordprocessingml.HtmlToWmlConverter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.xml.msofficexml.docx.wordprocessingml;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.hfg.css.*;
import com.hfg.exception.ProgrammingException;
import com.hfg.graphics.units.Pixels;
import com.hfg.graphics.units.Points;
import com.hfg.html.*;
import com.hfg.html.attribute.HTMLColor;
import com.hfg.util.collection.CollectionUtil;
import com.hfg.util.Recursion;
import com.hfg.util.StringUtil;
import com.hfg.util.io.GZIP;
import com.hfg.xml.XMLNode;
import com.hfg.xml.XMLTag;
import com.hfg.xml.msofficexml.docx.Docx;
import com.hfg.xml.msofficexml.docx.wordprocessingml.style.*;
//------------------------------------------------------------------------------
/**
* For converting HTML into WordprocessingML.
*
* @author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
public class HtmlToWmlConverter
{
private CSS mCSS;
private static final Pattern PTS_SIZE_PATTERN = Pattern.compile("(\\d+)(pt)?");
private static final Pattern PX_SIZE_PATTERN = Pattern.compile("(\\d+)(px)?");
//##########################################################################
// PUBLIC METHODS
//##########################################################################
//---------------------------------------------------------------------------
/**
Specify associated CSS to use during conversion.
@param inValue CSS object containing a collection of CSSRules
*/
public HtmlToWmlConverter setCSS(CSS inValue)
{
mCSS = inValue;
return this;
}
//---------------------------------------------------------------------------
/**
Warning: this method is still a brittle work-in-progress.
*/
public synchronized List convert(HTMLTag inHTMLTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.BR))
{
wmlTags.add(new WmlParagraph(inDocx).br());
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.DIV))
{
wmlTags.addAll(parseDivTag((Div) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.A))
{
wmlTags.addAll(parseLinkTag((Link) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.P))
{
wmlTags.addAll(parsePTag((P) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.PRE))
{
wmlTags.addAll(parsePreTag((Pre) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.SPAN))
{
wmlTags.addAll(parseSpanTag((Span) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.TABLE))
{
wmlTags.addAll(parseTableTag((Table) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.TBODY))
{
wmlTags.addAll(parseTBodyTag((TBody) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.THEAD))
{
wmlTags.addAll(parseTHeadTag((THead) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.TR))
{
wmlTags.addAll(parseTrTag((Tr) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.TH))
{
wmlTags.addAll(parseThTag((Th) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.TD))
{
wmlTags.addAll(parseTdTag((Td) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.H1))
{
wmlTags.addAll(parseH1Tag((H1) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.H2))
{
wmlTags.addAll(parseH2Tag((H2) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.LI))
{
wmlTags.addAll(parseLiTag((Li) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.UL))
{
wmlTags.addAll(parseUlTag((Ul) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.OL))
{
wmlTags.addAll(parseOlTag((Ol) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.NOBR))
{
wmlTags.addAll(parseNobrTag((Nobr) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.U))
{
wmlTags.addAll(parseSpanTag(inHTMLTag, new CSSDeclaration(CSSProperty.text_decoration, "underline"), inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.EM))
{
wmlTags.addAll(parseSpanTag(inHTMLTag, new CSSDeclaration(CSSProperty.font_style, "italic"), inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.B)
|| inHTMLTag.getTagName().equalsIgnoreCase(HTML.STRONG))
{
wmlTags.addAll(parseSpanTag(inHTMLTag, new CSSDeclaration(CSSProperty.font_weight, "bold"), inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.S))
{
wmlTags.addAll(parseSpanTag(inHTMLTag, new CSSDeclaration(CSSProperty.text_decoration, "line-through"), inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.HTML))
{
wmlTags.addAll(parseHtmlTag((HTML) inHTMLTag, inDocx));
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.CAPTION))
{
// Ignoring for now
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.COL))
{
// TODO: Ignore for now
}
else if (inHTMLTag.getTagName().equalsIgnoreCase(HTML.COLGROUP))
{
// TODO: Ignore for now
}
else
{
throw new ProgrammingException("No tag mapping for tag " + StringUtil.singleQuote(inHTMLTag.getTagName()));
}
// Replace any character entities (like """) with the corresponding numeric entities
if (CollectionUtil.hasValues(wmlTags))
{
for (XMLTag xmlTag : wmlTags)
{
xmlTag.replaceCharacterEntities();
}
}
return wmlTags;
}
//##########################################################################
// PRIVATE METHODS
//##########################################################################
//---------------------------------------------------------------------------
private List parseTableTag(Table inTableTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlTable table = new WmlTable(inDocx);
wmlTags.add(table);
List cssDeclarations = getCSSDeclarations(inTableTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTableProperties(cssDeclarations, table.getTableProperties());
}
// Was a cell padding size specified as a attribute value?
String cellPaddingString = inTableTag.getAttributeValue(HTML.CELLPADDING);
if (StringUtil.isSet(cellPaddingString))
{
table.getTableProperties().getTableCellMargins().addMargin(new WmlTableCellMargin(new Pixels(Integer.parseInt(cellPaddingString))));
}
// Was a border size specified as a attribute value?
String borderString = inTableTag.getAttributeValue(HTML.BORDER);
if (StringUtil.isSet(borderString))
{
WmlTableBorder border = new WmlTableBorder()
.setSize(new Pixels(Integer.parseInt(cellPaddingString)))
.setStyle(WmlLineBorderStyle.single)
.setColor(HTMLColor.BLACK);
table.getTableProperties().getBorders().addBorder(border);
}
if (inTableTag.hasContentOrSubtags())
{
for (XMLNode tableSubtag : inTableTag.getXMLNodeSubtags())
{
List subtags = convert((HTMLTag) tableSubtag, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
table.addSubtag(subtag);
}
}
}
}
// Apply any row merging
int currentRow = 0;
for (Tr htmlRow : inTableTag.getRows())
{
currentRow++;
List cellTags = htmlRow.getSubtags();
for (int cellIdx = 0; cellIdx < cellTags.size(); cellIdx++)
{
HTMLTag cellTag = cellTags.get(cellIdx);
if (cellTag.hasAttribute(HTML.ROWSPAN))
{
int rowSpan = Integer.parseInt(cellTag.getAttributeValue(HTML.ROWSPAN));
if (rowSpan > 1)
{
List tableRows = table.getRows();
// The first cell is marked with RESTART
WmlTableCell firstMergedCell = tableRows.get(currentRow - 1).getCells().get(cellIdx);
firstMergedCell.getCellProperties().setVerticalMerge(WmlVerticalMerge.RESTART);
// Subsequent merged cells (in the subsequent rows) are marked CONTINUE
for (int rowIdx = currentRow; rowIdx < currentRow + rowSpan - 1; rowIdx++)
{
WmlTableRow row = tableRows.get(rowIdx);
// Make sure enough cells have been defined
List cells = row.getCells();
int cellCount = cells.size();
while (cellCount < cellIdx + 1)
{
row.addCell();
cellCount++;
}
WmlTableCell cell = row.getCells().get(cellIdx);
cell.getCellProperties()
.setVerticalMerge(WmlVerticalMerge.CONTINUE);
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
// The THead tag itself doesn't map to anything but any table data it contains should get parsed.
private List parseTHeadTag(THead inTHeadTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
if (inTHeadTag.hasContentOrSubtags())
{
for (XMLNode subtag : inTHeadTag.getXMLNodeSubtags())
{
List subtags = convert((HTMLTag) subtag, inDocx);
if (CollectionUtil.hasValues(subtags))
{
wmlTags.addAll(subtags);
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
// The TBody tag itself doesn't map to anything but any table data it contains should get parsed.
private List parseTBodyTag(TBody inTBodyTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
if (inTBodyTag.hasContentOrSubtags())
{
for (XMLNode tbodySubtag : inTBodyTag.getXMLNodeSubtags())
{
List subtags = convert((HTMLTag) tbodySubtag, inDocx);
if (CollectionUtil.hasValues(subtags))
{
wmlTags.addAll(subtags);
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseTrTag(Tr inTrTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
List cssDeclarations = getCSSDeclarations(inTrTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
for (CSSDeclaration cssDeclaration : cssDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.display
&& cssDeclaration.getValue().equals("none"))
{
return wmlTags;
}
}
}
WmlTableRow tr = new WmlTableRow(inDocx);
wmlTags.add(tr);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTableRowProperties(cssDeclarations, tr.getRowProperties());
}
WmlTableCellProperties tcPr = null;
if (CollectionUtil.hasValues(cssDeclarations))
{
tcPr = new WmlTableCellProperties(inDocx);
convertCSSToTableCellProperties(cssDeclarations, tcPr);
}
if (inTrTag.hasContentOrSubtags())
{
for (XMLNode trSubtag : inTrTag.getXMLNodeSubtags())
{
List subtags = convert((HTMLTag) trSubtag, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
tr.addSubtag(subtag);
}
}
}
}
// Copy the table cell properties down to any cells since OfficeOpenXML is brain damaged
if (tcPr != null)
{
for (XMLTag wmlTag : wmlTags)
{
List tableCells = wmlTag.getSubtagsByName(WmlXML.TABLE_CELL.getLocalName(), Recursion.ON);
if (CollectionUtil.hasValues(tableCells))
{
for (WmlTableCell tc : (List) (Object) tableCells)
{
tcPr.add(tc.getCellProperties());
tc.setCellProperties(tcPr);
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseTdTag(Td inTdTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlTableCell td = new WmlTableCell(inDocx);
wmlTags.add(td);
boolean containsCss = false;
WmlTextRunProperties textRunProperties = null;
List cssDeclarations = getCSSDeclarations(inTdTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
containsCss = true;
convertCSSToTableCellProperties(cssDeclarations, td.getCellProperties());
// Remove bgColor and border styles before setting text run properties
for (int i = 0; i < cssDeclarations.size(); i++)
{
CSSDeclaration cssDeclaration = cssDeclarations.get(i);
if (cssDeclaration.getProperty().equals(CSSProperty.background_color)
|| cssDeclaration.getProperty().equals(CSSProperty.border))
{
cssDeclarations.remove(i--);
}
}
textRunProperties = new WmlTextRunProperties(inDocx);
convertCSSToTextRunProperties(cssDeclarations, textRunProperties);
}
// Apply column merging (Note that row merging is dealt with at the table level)
String colSpanString = inTdTag.getColSpan();
if (StringUtil.isSet(colSpanString))
{
int colSpan = Integer.parseInt(colSpanString);
if (colSpan > 1)
{
td.getCellProperties()
.setGridSpan(colSpan);
}
}
if (inTdTag.hasContentOrSubtags())
{
WmlParagraph p = td.getParagraph();
for (Object content : inTdTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
if (! p.hasContentOrSubtags())
{
td.removeSubtag(p);
}
td.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else
{
p.addSubtag(subtag);
}
}
}
}
}
// Copy the text run properties on the cell down to any text runs since OfficeOpenXML is brain damaged
if (containsCss)
{
for (XMLTag wmlTag : wmlTags)
{
List paragraphs = wmlTag.getSubtagsByName(WmlXML.P.getLocalName(), Recursion.ON);
if (CollectionUtil.hasValues(paragraphs))
{
for (WmlParagraph paragraph : (List) (Object) paragraphs)
{
convertCSSToParagraphProperties(cssDeclarations, paragraph.getProperties());
}
}
List textRuns = wmlTag.getSubtagsByName(WmlXML.R.getLocalName(), Recursion.ON);
if (CollectionUtil.hasValues(textRuns))
{
for (WmlTextRun textRun : (List) (Object) textRuns)
{
WmlTextRunProperties parentProperties = (WmlTextRunProperties) textRunProperties.clone();
textRun.setProperties(parentProperties.combine(textRun.getProperties()));
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseThTag(Th inThTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlTableCell th = new WmlTableCell(inDocx);
wmlTags.add(th);
WmlTextRunProperties textRunProperties = null;
boolean containsCss = false;
List cssDeclarations = getCSSDeclarations(inThTag);
// Th should default to bold
CSSDeclaration bold = new CSSDeclaration(CSSProperty.font_weight, "bold");
if (CollectionUtil.hasValues(cssDeclarations))
{
cssDeclarations.add(0, bold);
}
else
{
cssDeclarations = new ArrayList<>(4);
cssDeclarations.add(bold);
}
if (CollectionUtil.hasValues(cssDeclarations))
{
containsCss = true;
convertCSSToTableCellProperties(cssDeclarations, th.getCellProperties());
// Remove bgColor and border styles before setting text run properties
for (int i = 0; i < cssDeclarations.size(); i++)
{
CSSDeclaration cssDeclaration = cssDeclarations.get(i);
if (cssDeclaration.getProperty().equals(CSSProperty.background_color)
|| cssDeclaration.getProperty().equals(CSSProperty.border))
{
cssDeclarations.remove(i--);
}
}
textRunProperties = new WmlTextRunProperties(inDocx);
convertCSSToTextRunProperties(cssDeclarations, textRunProperties);
}
if (inThTag.hasContentOrSubtags())
{
WmlParagraph p = th.getParagraph();
for (Object content : inThTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
if (! p.hasContentOrSubtags())
{
th.removeSubtag(p);
}
th.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else
{
p.addSubtag(subtag);
}
}
}
}
}
}
// Copy the text run properties on the cell down to any text runs since OfficeOpenXML is brain damaged
if (containsCss)
{
for (XMLTag wmlTag : wmlTags)
{
List paragraphs = wmlTag.getSubtagsByName(WmlXML.P.getLocalName(), Recursion.ON);
if (CollectionUtil.hasValues(paragraphs))
{
for (WmlParagraph paragraph : (List) (Object) paragraphs)
{
convertCSSToParagraphProperties(cssDeclarations, paragraph.getProperties());
}
}
List textRuns = wmlTag.getSubtagsByName(WmlXML.R.getLocalName(), Recursion.ON);
if (CollectionUtil.hasValues(textRuns))
{
for (WmlTextRun textRun : (List) (Object) textRuns)
{
WmlTextRunProperties parentProperties = (WmlTextRunProperties) textRunProperties.clone();
textRun.setProperties(parentProperties.combine(textRun.getProperties()));
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parsePreTag(Pre inPreTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
WmlStyle preStyle = inDocx.getStylesPart().getStyle("pre");
if (null == preStyle)
{
preStyle = new WmlParagraphStyle("pre", inDocx);
preStyle.getTextRunProperties().setFont("Courier");
inDocx.getStylesPart().addStyle(preStyle);
}
p.getProperties().setStyle(preStyle.getId());
List cssDeclarations = getCSSDeclarations(inPreTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, p.getProperties().getRunProperties());
}
if (inPreTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inPreTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
p.addSubtags(subtag.getSubtags());
}
else
{
p.addSubtag(subtag);
}
}
}
}
}
// Make sure all of the text runs use the pre style
for (XMLNode xmlTag : p.getXMLNodeSubtags())
{
if (xmlTag instanceof WmlTextRun)
{
((WmlTextRun)xmlTag).getProperties().setStyle(preStyle.getId());
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseDivTag(Div inDivTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
List cssDeclarations = getCSSDeclarations(inDivTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
for (CSSDeclaration cssDeclaration : cssDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.display
&& cssDeclaration.getValue().equals("none"))
{
return wmlTags;
}
}
}
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, p.getProperties().getRunProperties());
}
if (inDivTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inDivTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
wmlTags.add(subtag);
p = (WmlParagraph) subtag;
}
else
{
wmlTags.add(subtag);
containerClosed = true;
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseHtmlTag(HTML inHtmlTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
if (inHtmlTag.hasContentOrSubtags())
{
WmlParagraph p = new WmlParagraph(inDocx);
boolean containerClosed = false;
for (Object content : inHtmlTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
if (p.hasContentOrSubtags())
{
wmlTags.add(p);
containerClosed = true;
}
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (WmlXML.R.getLocalName().equalsIgnoreCase(subtag.getTagName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addSubtag(subtag);
}
else if (WmlXML.BR.getLocalName().equalsIgnoreCase(subtag.getTagName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else if (WmlXML.P.getLocalName().equalsIgnoreCase(subtag.getTagName()))
{
wmlTags.add(subtag);
containerClosed = true;
}
else
{
wmlTags.add(subtag);
containerClosed = true;
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseH1Tag(H1 inH1Tag, Docx inDocx)
{
return parseHeadingTag(inH1Tag, inDocx);
}
//---------------------------------------------------------------------------
private List parseH2Tag(H2 inH1Tag, Docx inDocx)
{
return parseHeadingTag(inH1Tag, inDocx);
}
//---------------------------------------------------------------------------
private List parseH3Tag(H3 inH1Tag, Docx inDocx)
{
return parseHeadingTag(inH1Tag, inDocx);
}
//---------------------------------------------------------------------------
private List parseHeadingTag(HTMLTag inHTMLTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
String styleId = null;
if (inHTMLTag instanceof H1)
{
styleId = WmlParagraphStyle.HEADING1_STYLE_ID;
}
else if (inHTMLTag instanceof H2)
{
styleId = WmlParagraphStyle.HEADING2_STYLE_ID;
}
// TODO: Add support for H3 and H4
if (styleId != null)
{
p.getProperties().setStyle(styleId);
}
List cssDeclarations = getCSSDeclarations(inHTMLTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, p.getProperties().getRunProperties());
}
if (inHTMLTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inHTMLTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
wmlTags.add(subtag);
p = (WmlParagraph) subtag;
}
else
{
wmlTags.add(subtag);
containerClosed = true;
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parsePTag(P inPTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
WmlTextRunProperties runProperties = new WmlTextRunProperties(inDocx);
List cssDeclarations = getCSSDeclarations(inPTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
// convertCSSToTextRunProperties(cssDeclarations, p.getProperties().getRunProperties());
convertCSSToTextRunProperties(cssDeclarations, runProperties);
}
if (inPTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inPTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun((String) content).setProperties(runProperties);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun(GZIP.uncompressToString((byte[]) content)).setProperties(runProperties);
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
WmlTextRun textRun = p.addTextRun();
textRun.setProperties(runProperties);
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
wmlTags.add(subtag);
p = (WmlParagraph) subtag;
}
else
{
wmlTags.add(subtag);
containerClosed = true;
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseSpanTag(Span inSpanTag, Docx inDocx)
{
return parseSpanTag(inSpanTag, null, inDocx);
}
//---------------------------------------------------------------------------
private List parseSpanTag(HTMLTag inSpanTag, CSSDeclaration inCSS, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
List cssDeclarations = getCSSDeclarations(inSpanTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
for (CSSDeclaration cssDeclaration : cssDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.display
&& cssDeclaration.getValue().equals("none"))
{
return wmlTags;
}
}
}
if (inCSS != null)
{
if (null == cssDeclarations)
{
cssDeclarations = new ArrayList<>(1);
}
cssDeclarations.add(inCSS);
}
WmlTextRun textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, textRun.getProperties());
}
if (inSpanTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inSpanTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, textRun.getProperties());
}
}
textRun.addText((String)content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
textRun = new WmlTextRun(inDocx);
}
textRun.addText(GZIP.uncompressToString((byte[]) content));
}
else
{
if (! textRun.hasContentOrSubtags())
{
wmlTags.remove(textRun);
}
containerClosed = true;
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
// Word won't allow nesting of text runs
containerClosed = true;
WmlTextRun runSubtag = (WmlTextRun) subtag;
if (textRun.hasProperties())
{
WmlTextRunProperties parentProperties = (WmlTextRunProperties) textRun.getProperties().clone();
runSubtag.setProperties(parentProperties.combine(runSubtag.getProperties()));
}
wmlTags.add(runSubtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed
|| textRun.hasContentOrSubtags())
{
containerClosed = true;
textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
}
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
wmlTags.addAll(subtag.getSubtags());
}
else
{
wmlTags.add(subtag);
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
// The Link (A) tag itself doesn't map to anything but any data it contains should get parsed.
private List parseLinkTag(Link inLinkTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
try
{
if (inLinkTag.hasContentOrSubtags())
{
WmlHyperlink link = null;
boolean containerClosed = true;
for (Object content : inLinkTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
link = new WmlHyperlink(new URL(inLinkTag.getURL()), inDocx);
wmlTags.add(link);
}
link.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
link = new WmlHyperlink(new URL(inLinkTag.getURL()), inDocx);
wmlTags.add(link);
}
link.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
if (containerClosed)
{
link = new WmlHyperlink(new URL(inLinkTag.getURL()), inDocx);
wmlTags.add(link);
}
link.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
if (containerClosed)
{
link = new WmlHyperlink(new URL(inLinkTag.getURL()), inDocx);
wmlTags.add(link);
}
for (XMLNode runTag : subtag.getSubtagsByName(WmlXML.R))
{
link.addSubtag(runTag);
}
}
else
{
if (containerClosed)
{
link = new WmlHyperlink(new URL(inLinkTag.getURL()), inDocx);
wmlTags.add(link);
}
link.addSubtag(subtag);
}
}
}
}
}
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
return wmlTags;
}
//---------------------------------------------------------------------------
// The Nobr tag itself doesn't map to anything but any data it contains should get parsed.
private List parseNobrTag(Nobr inNobrTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
if (inNobrTag.hasContentOrSubtags())
{
WmlTextRun textRun = null;
boolean containerClosed = true;
for (Object content : inNobrTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
}
textRun.addText((String)content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
textRun = new WmlTextRun(inDocx);
}
textRun.addText(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
// Word won't allow nesting of text runs
containerClosed = true;
WmlTextRun runSubtag = (WmlTextRun) subtag;
if (textRun.hasProperties())
{
WmlTextRunProperties parentProperties = (WmlTextRunProperties) textRun.getProperties().clone();
runSubtag.setProperties(parentProperties.combine(runSubtag.getProperties()));
}
wmlTags.add(runSubtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed
|| textRun.hasContentOrSubtags())
{
containerClosed = true;
textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
}
textRun.addSubtag(subtag);
}
else if (containerClosed)
{
textRun = new WmlTextRun(inDocx);
wmlTags.add(textRun);
textRun.addSubtag(subtag);
}
else
{
textRun.addSubtag(subtag);
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseLiTag(Li inLiTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
List cssDeclarations = getCSSDeclarations(inLiTag);
if (CollectionUtil.hasValues(cssDeclarations))
{
convertCSSToTextRunProperties(cssDeclarations, p.getProperties().getRunProperties());
}
if (inLiTag.hasContentOrSubtags())
{
boolean containerClosed = false;
for (Object content : inLiTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag.getTagName().equalsIgnoreCase(WmlXML.R.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
p.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.BR.getLocalName()))
{
if (containerClosed)
{
p = new WmlParagraph(inDocx);
wmlTags.add(p);
containerClosed = false;
}
WmlTextRun textRun = p.addTextRun();
textRun.addSubtag(subtag);
}
else if (subtag.getTagName().equalsIgnoreCase(WmlXML.P.getLocalName()))
{
wmlTags.add(subtag);
p = (WmlParagraph) subtag;
}
else
{
wmlTags.add(subtag);
containerClosed = true;
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseUlTag(Ul inUlTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlUnorderedList list = new WmlUnorderedList(inDocx);
wmlTags.add(list);
if (inUlTag.hasContentOrSubtags())
{
for (Object content : inUlTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag instanceof WmlParagraph)
{
list.addItem((WmlParagraph) subtag);
}
else if (subtag instanceof WmlList)
{
int lastLevel = list.getLastLevel();
for (WmlParagraph item : ((WmlList) subtag).getItems())
{
list.addItem(item, lastLevel + 1 + item.getProperties().getNumberingProperties().getLevel());
}
}
else
{
list.addSubtag(subtag);
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
private List parseOlTag(Ol inOlTag, Docx inDocx)
{
List wmlTags = new ArrayList<>(5);
WmlOrderedList list = new WmlOrderedList(inDocx);
wmlTags.add(list);
if (inOlTag.hasContentOrSubtags())
{
for (Object content : inOlTag.getContentPlusSubtagList())
{
if (content instanceof String)
{
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
p.addTextRun((String) content);
}
else if (content instanceof byte[]) // Compressed content is stored as a byte[]
{
WmlParagraph p = new WmlParagraph(inDocx);
wmlTags.add(p);
p.addTextRun(GZIP.uncompressToString((byte[]) content));
}
else
{
List subtags = convert((HTMLTag) content, inDocx);
if (CollectionUtil.hasValues(subtags))
{
for (XMLTag subtag: subtags)
{
if (subtag instanceof WmlParagraph)
{
list.addItem((WmlParagraph) subtag);
}
else if (subtag instanceof WmlList)
{
int lastLevel = list.getLastLevel();
for (WmlParagraph item : ((WmlList) subtag).getItems())
{
list.addItem(item, lastLevel + 1 + item.getProperties().getNumberingProperties().getLevel());
}
}
else
{
list.addSubtag(subtag);
}
}
}
}
}
}
return wmlTags;
}
//---------------------------------------------------------------------------
// Returns the in-line and CSS-defined styling for the specified tag.
private List getCSSDeclarations(HTMLTag inHTMLTag)
{
List cssDeclarations = new ArrayList<>(20);
if (mCSS != null)
{
List declarations = mCSS.getCSSDeclarationsForHTMLTag(inHTMLTag, CSSMediaType.print);
if (CollectionUtil.hasValues(declarations))
{
cssDeclarations.addAll(declarations);
}
}
String styleString = inHTMLTag.getStyle();
if (StringUtil.isSet(styleString))
{
List styleCSSDeclarations = parseCssStyleString(styleString);
if (CollectionUtil.hasValues(styleCSSDeclarations))
{
cssDeclarations.addAll(styleCSSDeclarations);
}
}
return cssDeclarations;
}
//---------------------------------------------------------------------------
private void convertCSSToParagraphProperties(List inCSSDeclarations, WmlParagraphProperties inParagraphProperties)
{
for (CSSDeclaration cssDeclaration : inCSSDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.text_align)
{
WmlJustification justification = null;
if (cssDeclaration.getValue().equalsIgnoreCase("center"))
{
justification = WmlJustification.center;
}
else if (cssDeclaration.getValue().equalsIgnoreCase("left"))
{
justification = WmlJustification.left;
}
else if (cssDeclaration.getValue().equalsIgnoreCase("right"))
{
justification = WmlJustification.right;
}
if (justification != null)
{
inParagraphProperties.setJustification(justification);
}
}
}
}
//---------------------------------------------------------------------------
private void convertCSSToTextRunProperties(List inCSSDeclarations, WmlTextRunProperties inTextRunProperties)
{
for (CSSDeclaration cssDeclaration : inCSSDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.color)
{
HTMLColor color = HTMLColor.valueOf(cssDeclaration.getValue());
if (color != null)
{
inTextRunProperties.setColor(color);
}
}
else if (cssDeclaration.getProperty() == CSSProperty.background_color)
{
HTMLColor color = HTMLColor.valueOf(cssDeclaration.getValue());
if (color != null)
{
inTextRunProperties.getShading().setFill(color);
}
}
else if (cssDeclaration.getProperty() == CSSProperty.font_weight
&& cssDeclaration.getValue().equalsIgnoreCase("bold"))
{
inTextRunProperties.setBold();
}
else if (cssDeclaration.getProperty() == CSSProperty.font_style
&& cssDeclaration.getValue().equalsIgnoreCase("italic"))
{
inTextRunProperties.setItalics();
}
else if (cssDeclaration.getProperty() == CSSProperty.font_size)
{
if (cssDeclaration.getValue().endsWith("pt"))
{
Matcher m = PTS_SIZE_PATTERN.matcher(cssDeclaration.getValue());
if (m.matches())
{
inTextRunProperties.setSize(new Points(Integer.parseInt(m.group(1))));
}
}
else if (cssDeclaration.getValue().endsWith("px"))
{
Matcher m = PX_SIZE_PATTERN.matcher(cssDeclaration.getValue());
if (m.matches())
{
inTextRunProperties.setSize(new Pixels(Integer.parseInt(m.group(1))));
}
}
// Don't know what to do with 'em' sizes
}
else if (cssDeclaration.getProperty() == CSSProperty.border)
{
inTextRunProperties.getBorder(cssDeclaration);
}
else if (cssDeclaration.getProperty() == CSSProperty.text_decoration
&& cssDeclaration.getValue().equalsIgnoreCase("underline"))
{
inTextRunProperties.setUnderline();
}
else if (cssDeclaration.getProperty() == CSSProperty.text_decoration
&& cssDeclaration.getValue().equalsIgnoreCase("line-through"))
{
inTextRunProperties.setStrikeThrough();
}
}
}
//---------------------------------------------------------------------------
private void convertCSSToTableProperties(List inCSSDeclarations, WmlTableProperties inTableProperties)
{
for (CSSDeclaration cssDeclaration : inCSSDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.margin)
{
inTableProperties.getTableCellMargins().addMargins(cssDeclaration);
}
else if (cssDeclaration.getProperty() == CSSProperty.width
&& cssDeclaration.getValue().endsWith("px"))
{
// Don't know what to do with 'em' sizes
Matcher m = PX_SIZE_PATTERN.matcher(cssDeclaration.getValue());
if (m.matches())
{
inTableProperties.setWidth(new Pixels(Integer.parseInt(m.group(1))));
}
}
}
}
//---------------------------------------------------------------------------
private void convertCSSToTableCellProperties(List inCSSDeclarations, WmlTableCellProperties inTableCellProperties)
{
for (CSSDeclaration cssDeclaration : inCSSDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.background_color)
{
HTMLColor color = HTMLColor.valueOf(cssDeclaration.getValue());
if (color != null)
{
inTableCellProperties.getShading().setFill(color);
}
}
else if (cssDeclaration.getProperty() == CSSProperty.vertical_align)
{
WmlVerticalJustification justification = null;
if (cssDeclaration.getValue().equalsIgnoreCase("middle"))
{
justification = WmlVerticalJustification.center;
}
else if (cssDeclaration.getValue().equalsIgnoreCase("top"))
{
justification = WmlVerticalJustification.top;
}
else if (cssDeclaration.getValue().equalsIgnoreCase("bottom"))
{
justification = WmlVerticalJustification.bottom;
}
if (justification != null)
{
inTableCellProperties.setVerticalJustification(justification);
}
}
else if ((cssDeclaration.getProperty() == CSSProperty.border
|| cssDeclaration.getProperty() == CSSProperty.border_top
|| cssDeclaration.getProperty() == CSSProperty.border_bottom
|| cssDeclaration.getProperty() == CSSProperty.border_left
|| cssDeclaration.getProperty() == CSSProperty.border_right)
&& ! cssDeclaration.getValue().equalsIgnoreCase("none"))
{
inTableCellProperties.getBorders().addBorder(new WmlTableCellBorder(cssDeclaration));
}
else if (cssDeclaration.getProperty() == CSSProperty.width
&& cssDeclaration.getValue().endsWith("px"))
{
// Don't know what to do with 'em' sizes
Matcher m = PX_SIZE_PATTERN.matcher(cssDeclaration.getValue());
if (m.matches())
{
inTableCellProperties.setWidth(new Pixels(Integer.parseInt(m.group(1))));
}
}
else if (cssDeclaration.getProperty() == CSSProperty.transform)
{
if (cssDeclaration.getValue().equals("rotate(-90deg)"))
{
inTableCellProperties.setTextDirection(WmlTextDirection.btLr);
}
}
}
}
//---------------------------------------------------------------------------
private void convertCSSToTableRowProperties(List inCSSDeclarations, WmlTableRowProperties inTableRowProperties)
{
for (CSSDeclaration cssDeclaration : inCSSDeclarations)
{
if (cssDeclaration.getProperty() == CSSProperty.height
&& cssDeclaration.getValue().endsWith("px"))
{
// Don't know what to do with 'em' sizes
Matcher m = PX_SIZE_PATTERN.matcher(cssDeclaration.getValue());
if (m.matches())
{
inTableRowProperties.setExactHeight(new Pixels(Integer.parseInt(m.group(1))));
}
}
}
}
//---------------------------------------------------------------------------
private List parseCssStyleString(String inCssStyleString)
{
List cssDeclarations = new ArrayList<>(20);
String[] pieces = inCssStyleString.split(";");
for (String piece : pieces)
{
int colonIdx = piece.indexOf(":");
CSSProperty property = CSSProperty.valueOf(piece.substring(0, colonIdx).trim());
if (property != null)
{
String value = piece.substring(colonIdx + 1).trim();
cssDeclarations.add(new CSSDeclaration(property, value));
}
}
return cssDeclarations;
}
}