|
import net.sf.saxon.Configuration;
|
|
import net.sf.saxon.TransformerFactoryImpl;
|
|
import net.sf.saxon.om.DocumentInfo;
|
|
import net.sf.saxon.om.NodeInfo;
|
|
import net.sf.saxon.pull.PullPushCopier;
|
|
import net.sf.saxon.pull.StaxBridge;
|
|
import net.sf.saxon.trans.XPathException;
|
|
import net.sf.saxon.tree.tiny.TinyBuilder;
|
|
import net.sf.saxon.type.Type;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
import org.w3c.dom.Document;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import javax.xml.stream.XMLInputFactory;
|
|
import javax.xml.stream.XMLStreamException;
|
|
import javax.xml.stream.XMLStreamReader;
|
|
import javax.xml.transform.*;
|
|
import javax.xml.transform.dom.DOMResult;
|
|
import javax.xml.transform.dom.DOMSource;
|
|
import javax.xml.transform.stream.StreamResult;
|
|
import javax.xml.transform.stream.StreamSource;
|
|
import java.io.*;
|
|
import java.nio.charset.Charset;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Map;
|
|
|
|
|
|
public class CopyXSLTest {
|
|
|
|
|
|
public static final TransformerFactoryImpl TRANSFORMER_FACTORY = new TransformerFactoryImpl();
|
|
public static final Configuration CONFIGURATION = TRANSFORMER_FACTORY.getConfiguration();
|
|
private static XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance();
|
|
private static DocumentBuilderFactory DOM_FACTORY = DocumentBuilderFactory.newInstance();
|
|
|
|
@DataProvider(name = "copy")
|
|
private Object[][] copyCases() {
|
|
return new Object[][]{
|
|
{"1", "before.xml"}
|
|
};
|
|
}
|
|
|
|
|
|
@Test(dataProvider = "copyCases")
|
|
public void testTransformation(String testName, String payloadPath) throws Exception {
|
|
|
|
final Templates templates = TRANSFORMER_FACTORY.newTemplates(new StreamSource(loadFileFromClasspath("Copy.xsl")));
|
|
final String payload = loadClassPathContent(payloadPath);
|
|
|
|
System.out.println("Input DocumentInfo - TinyBuilder result -> output incorrect");
|
|
DocumentInfo docInfoResult = (DocumentInfo)runXslTransformation(templates, toDocumentInfo(toNodeInfo(payload)), true);
|
|
System.out.println(transformXmlToString(docInfoResult));
|
|
|
|
System.out.println("Input DocumentInfo - DomResult -> output correct");
|
|
Document domResult = (Document) runXslTransformation(templates, toDocumentInfo(toNodeInfo(payload)), false);
|
|
System.out.println(transformXmlToString(new DOMSource(domResult)));
|
|
|
|
System.out.println("Input W3C Document - TinyBuilder result -> output correct");
|
|
docInfoResult = (DocumentInfo)runXslTransformation(templates, toDocument(payload), true);
|
|
System.out.println(transformXmlToString(docInfoResult));
|
|
|
|
|
|
System.out.println();
|
|
System.out.println("Input W3C Document - DomResult -> output correct");
|
|
|
|
domResult = (Document) runXslTransformation(templates, toDocument(payload), false);
|
|
System.out.println(transformXmlToString(new DOMSource(domResult)));
|
|
}
|
|
|
|
|
|
|
|
public static InputStream loadFileFromClasspath(String fileClassPath) {
|
|
return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileClassPath);
|
|
}
|
|
|
|
public static String loadClassPathContent(String fileClassPath) throws IOException {
|
|
return IOUtils.toString(loadFileFromClasspath(fileClassPath), StandardCharsets.UTF_8);
|
|
}
|
|
|
|
|
|
public static Object runXslTransformation(Templates template, Object input, boolean useTinyResult) throws TransformerException {
|
|
return runXslTransformation(template, input, null, useTinyResult);
|
|
}
|
|
|
|
public static Object runXslTransformation(Templates template, Object input, Map<String, Object> parameters, boolean useTinyResult) throws TransformerException {
|
|
Transformer transformer = template.newTransformer();
|
|
if (parameters != null) {
|
|
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
|
|
transformer.setParameter(entry.getKey(), entry.getValue());
|
|
}
|
|
}
|
|
|
|
Source inputSource;
|
|
if (input instanceof DocumentInfo) {
|
|
inputSource = (javax.xml.transform.Source) input;
|
|
} else if (input instanceof Document){
|
|
inputSource = new DOMSource((org.w3c.dom.Node) input);
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
Result result = useTinyResult ? new TinyBuilder(CONFIGURATION.makePipelineConfiguration()) : new DOMResult();
|
|
transformer.transform(inputSource, result);
|
|
|
|
if (useTinyResult){
|
|
return ((TinyBuilder)result).getCurrentRoot();
|
|
} else {
|
|
return ((DOMResult)result).getNode();
|
|
}
|
|
}
|
|
|
|
|
|
public static DocumentInfo toDocumentInfo(NodeInfo nodeInfo) throws TransformerException {
|
|
if (nodeInfo == null) {
|
|
return null;
|
|
} else {
|
|
int nodeKind = nodeInfo.getNodeKind();
|
|
if (Type.DOCUMENT == nodeKind) {
|
|
return (DocumentInfo) nodeInfo;
|
|
} else if (Type.ELEMENT == nodeKind) {
|
|
NodeInfo nodeInfoParent = nodeInfo.getParent();
|
|
if (nodeInfoParent != null && nodeInfoParent.getNodeKind() == Type.DOCUMENT) {
|
|
return (DocumentInfo) nodeInfoParent;
|
|
} else {
|
|
return (DocumentInfo) toNodeInfoGeneral(nodeInfo);
|
|
}
|
|
}
|
|
throw new TransformerException("Unable to convert Node (NodeKind: " + nodeKind + ") to a Document");
|
|
}
|
|
}
|
|
|
|
public static NodeInfo toNodeInfo(String string) throws XPathException, XMLStreamException {
|
|
return toNodeInfo(INPUT_FACTORY.createXMLStreamReader(new StringReader(string)));
|
|
}
|
|
|
|
public static NodeInfo toNodeInfo(XMLStreamReader xmlStreamReader) throws XPathException {
|
|
StaxBridge parser = new StaxBridge();
|
|
parser.setXMLStreamReader(xmlStreamReader);
|
|
parser.setPipelineConfiguration(CONFIGURATION.makePipelineConfiguration());
|
|
TinyBuilder builder = new TinyBuilder(parser.getPipelineConfiguration());
|
|
new PullPushCopier(parser, builder).copy();
|
|
return builder.getCurrentRoot();
|
|
}
|
|
|
|
private static NodeInfo toNodeInfoGeneral(Source source) throws TransformerException {
|
|
Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
|
|
TinyBuilder builder = new TinyBuilder(CONFIGURATION.makePipelineConfiguration());
|
|
transformer.transform(source, builder);
|
|
return builder.getCurrentRoot();
|
|
}
|
|
|
|
public static String transformXmlToString(Source source) throws TransformerException {
|
|
StringWriter buffer = new StringWriter();
|
|
transformSourceToResult(source, StandardCharsets.UTF_8, true, new StreamResult(buffer));
|
|
return buffer.toString();
|
|
}
|
|
|
|
|
|
public static void transformSourceToResult(Source source, Charset charset, boolean indent, Result result) throws TransformerException {
|
|
Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
|
|
transformer.setOutputProperty(OutputKeys.ENCODING, charset.name());
|
|
transformer.setOutputProperty(OutputKeys.INDENT, indent ? "yes" : "no");
|
|
transformer.transform(source, result);
|
|
}
|
|
|
|
|
|
public static Document toDocument(String xml) throws IOException, SAXException {
|
|
return toDocument(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
|
|
}
|
|
|
|
public static Document toDocument(InputStream inputStream) throws IOException, SAXException {
|
|
DocumentBuilder documentBuilder = createDocumentBuilder();
|
|
return documentBuilder.parse(inputStream);
|
|
}
|
|
|
|
public static DocumentBuilder createDocumentBuilder() {
|
|
try {
|
|
return DOM_FACTORY.newDocumentBuilder();
|
|
} catch (ParserConfigurationException e) {
|
|
throw new IllegalStateException("Unable to create DOM DocumentBuilder", e);
|
|
}
|
|
}
|
|
}
|