package org.apache.poi.xssf.usermodel;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.EnumMap;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.w3c.dom.ls.DOMImplementationLS;
-import org.w3c.dom.ls.LSSerializer;
+
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
/**
- * Table style names defined in the OOXML spec.
+ * Table style names defined in the OOXML spec.
* The actual styling is defined in presetTableStyles.xml
*/
public enum XSSFBuiltinTableStyle {
PivotStyleDark27,
/***/
PivotStyleDark28,
- ;
-
+ ;
+
/**
* Interestingly, this is initialized after the enum instances, so using an {@link EnumMap} works.
*/
private static final Map<XSSFBuiltinTableStyle, TableStyle> styleMap = new EnumMap<>(XSSFBuiltinTableStyle.class);
-
+
private XSSFBuiltinTableStyle() {
}
-
+
/**
* @return built-in {@link TableStyle} definition
*/
init();
return styleMap.get(this);
}
-
+
/**
* NOTE: only checks by name, not definition.
+ *
* @param style
* @return true if the style represents a built-in style, false if it is null or a custom style
*/
return false;
}
}
+
/**
* Only init once - thus the synchronized. Lazy, after creating instances,
* and only when a style is actually needed, to avoid overhead for uses
* during evaluation if desired.
*/
public static synchronized void init() {
- if (! styleMap.isEmpty()) return;
-
+ if (!styleMap.isEmpty()) return;
+
/*
* initialize map. Every built-in has this format:
* <styleName>
final InputStream is = XSSFBuiltinTableStyle.class.getResourceAsStream("presetTableStyles.xml");
try {
final Document doc = DocumentHelper.readDocument(is);
-
+
final NodeList styleNodes = doc.getDocumentElement().getChildNodes();
- for (int i=0; i < styleNodes.getLength(); i++) {
+ for (int i = 0; i < styleNodes.getLength(); i++) {
final Node node = styleNodes.item(i);
if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements
final Element tag = (Element) node;
String styleName = tag.getTagName();
XSSFBuiltinTableStyle builtIn = XSSFBuiltinTableStyle.valueOf(styleName);
-
+
Node dxfsNode = tag.getElementsByTagName("dxfs").item(0);
Node tableStyleNode = tag.getElementsByTagName("tableStyles").item(0);
-
+
// hack because I can't figure out how to get XMLBeans to parse a sub-element in a standalone manner
// - build a fake styles.xml file with just this built-in
StylesTable styles = new StylesTable();
throw new RuntimeException(e);
}
}
-
- private static String styleXML(Node dxfsNode, Node tableStyleNode) {
+
+ private static String styleXML(Node dxfsNode, Node tableStyleNode) throws IOException, TransformerException {
// built-ins doc uses 1-based dxf indexing, Excel uses 0 based.
// add a dummy node to adjust properly.
dxfsNode.insertBefore(dxfsNode.getOwnerDocument().createElement("dxf"), dxfsNode.getFirstChild());
- DOMImplementationLS lsImpl = (DOMImplementationLS)dxfsNode.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
- LSSerializer lsSerializer = lsImpl.createLSSerializer();
- lsSerializer.getDomConfig().setParameter("xml-declaration", false);
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n")
- .append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" "
- + "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" "
- + "xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" "
- + "xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" "
- + "mc:Ignorable=\"x14ac x16r2\">\n");
- sb.append(lsSerializer.writeToString(dxfsNode));
- sb.append(lsSerializer.writeToString(tableStyleNode));
- sb.append("</styleSheet>");
- return sb.toString();
+ .append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ")
+ .append("xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ")
+ .append("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" ")
+ .append("xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" ")
+ .append("mc:Ignorable=\"x14ac x16r2\">\n");
+ sb.append(writeToString(dxfsNode));
+ sb.append(writeToString(tableStyleNode));
+ sb.append("</styleSheet>");
+ return sb.toString();
+ }
+
+ private static String writeToString(Node node) throws IOException, TransformerException {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ try (StringWriter sw = new StringWriter()){
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ transformer.transform(new DOMSource(node), new StreamResult(sw));
+ return sw.toString();
+ }
}
-
+
/**
* implementation for built-in styles
*/
this.builtIn = builtIn;
this.style = style;
}
-
+
public String getName() {
return style.getName();
}
public boolean isBuiltin() {
return true;
}
-
+
public DifferentialStyleProvider getStyle(TableStyleType type) {
return style.getStyle(type);
}
-
+
}
}