diff --git a/CHANGELOG.md b/CHANGELOG.md index ff326a3a..7461376a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.4.0] - 2023-09-30 + +### Added + +- transformer config facility +- xml white space remove utility +- StreamHelper.resolveReader() method + ### Changed - fj-bom version set to 1.4.7 diff --git a/fj-core/src/main/java/org/fugerit/java/core/io/helper/StreamHelper.java b/fj-core/src/main/java/org/fugerit/java/core/io/helper/StreamHelper.java index 7692ba58..3b6f7f9f 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/io/helper/StreamHelper.java +++ b/fj-core/src/main/java/org/fugerit/java/core/io/helper/StreamHelper.java @@ -25,6 +25,7 @@ import java.io.Flushable; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; @@ -63,6 +64,10 @@ private StreamHelper() {} public static final String PATH_JNDI = MODE_JNDI+URL_HELPER; + public static Reader resolveReader( String path ) throws IOException { + return new InputStreamReader( resolveStream( path, null ) ); + } + public static InputStream resolveStream( String path ) throws IOException { return resolveStream( path, null ); } diff --git a/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerConfig.java b/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerConfig.java new file mode 100644 index 00000000..80235120 --- /dev/null +++ b/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerConfig.java @@ -0,0 +1,74 @@ +package org.fugerit.java.core.xml; + +import java.util.Map; +import java.util.Properties; +import java.util.stream.Stream; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; + +public final class TransformerConfig { + + public static final String YES = "yes"; + public static final String NO = "no"; + + private Properties outputProperties; + + private TransformerConfig() { + this.outputProperties = new Properties(); + } + + public static TransformerConfig newConfig() { + return new TransformerConfig(); + } + + public void setAll( Transformer t ) { + t.setOutputProperties( this.outputProperties ); + } + + public Stream> stream() { + return this.outputProperties.entrySet().stream(); + } + + public TransformerConfig add( String key, String value ) { + this.outputProperties.setProperty(key, value); + return this; + } + + public TransformerConfig omitXmlDeclarationYes() { + return this.add( OutputKeys.OMIT_XML_DECLARATION, YES ); + } + + public TransformerConfig omitXmlDeclarationNo() { + return this.add( OutputKeys.OMIT_XML_DECLARATION, NO ); + } + + public TransformerConfig indentYes() { + return this.add( OutputKeys.INDENT, YES ); + } + + public TransformerConfig indentNo() { + return this.add( OutputKeys.INDENT, NO ); + } + + public TransformerConfig methodXml() { + return this.method( "xml" ); + } + + public TransformerConfig method( String value ) { + return this.add( OutputKeys.METHOD, value ); + } + + public TransformerConfig indentAmount( int indentAmount ) { + return this.add( "{http://xml.apache.org/xslt}indent-amount", String.valueOf( indentAmount ) ); + } + + public static TransformerConfig newIndentConfig( Integer indentAmount ) { + TransformerConfig config = newConfig().indentYes().methodXml().omitXmlDeclarationYes(); + if ( indentAmount != null ) { + config = config.indentAmount( indentAmount.intValue() ); + } + return config; + } + +} diff --git a/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerXML.java b/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerXML.java index 287932dc..917ef38b 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerXML.java +++ b/fj-core/src/main/java/org/fugerit/java/core/xml/TransformerXML.java @@ -45,6 +45,18 @@ public static TransformerFactory newSafeTransformerFactory( Properties features public static TransformerFactory newSafeTransformerFactory() { return newSafeTransformerFactory( NO_FEATURES ); } + + public static Transformer newTransformerWithConfig(TransformerConfig config) throws XMLException { + Transformer transformer = newTransformer(); + config.setAll(transformer); + return transformer; + } + + public static Transformer newTransformer(Source source, TransformerConfig config) throws XMLException { + Transformer transformer = newTransformer( source ); + config.setAll(transformer); + return transformer; + } public static Transformer newTransformer(Source source) throws XMLException { Transformer transformer = null; @@ -61,7 +73,7 @@ public static Transformer newTransformer(Source source) throws XMLException { } public static Transformer newTransformer() throws XMLException { - return newTransformer(null); + return newTransformer( null ); } } diff --git a/fj-core/src/main/java/org/fugerit/java/core/xml/XMLWhiteSpaceRemove.java b/fj-core/src/main/java/org/fugerit/java/core/xml/XMLWhiteSpaceRemove.java new file mode 100644 index 00000000..768132a1 --- /dev/null +++ b/fj-core/src/main/java/org/fugerit/java/core/xml/XMLWhiteSpaceRemove.java @@ -0,0 +1,47 @@ +package org.fugerit.java.core.xml; + +import java.io.Reader; +import java.io.Writer; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.fugerit.java.core.io.helper.StreamHelper; +import org.w3c.dom.Node; + +public class XMLWhiteSpaceRemove { + + public static final String PATH_REMOVE_WHITESPACE_NODES_XSLT = StreamHelper.PATH_CLASSLOADER+"core/xml/remove_whitespace_nodes.xslt"; + + private XMLWhiteSpaceRemove() {} + + public static void cleanBlankNodesIndent2( Node node, Writer writer ) throws XMLException { + cleanBlankNodes( node, writer, TransformerConfig.newIndentConfig( 2 )); + } + + public static void cleanBlankNodes( Node node, Writer writer, TransformerConfig config ) throws XMLException { + cleanBlankNodes( node, new StreamResult( writer ), config); + } + + public static void cleanBlankNodes( Node node, Result result, TransformerConfig config ) throws XMLException { + cleanBlankNodes( new DOMSource( node ), result, config); + } + + public static void cleanBlankNodes( Source source, Result result, TransformerConfig config ) throws XMLException { + cleanBlankNodes(source, result, config, PATH_REMOVE_WHITESPACE_NODES_XSLT); + } + + public static void cleanBlankNodes( Source source, Result result, TransformerConfig config, String xlstPath ) throws XMLException { + XMLException.apply( () -> { + try ( Reader xlstClean = StreamHelper.resolveReader(xlstPath) ) { + Transformer t = TransformerXML.newTransformer( new StreamSource( xlstClean ), config ); + t.transform( source , result ); + } + }); + } + +} diff --git a/fj-core/src/main/resources/core/xml/remove_whitespace_nodes.xslt b/fj-core/src/main/resources/core/xml/remove_whitespace_nodes.xslt new file mode 100644 index 00000000..3941269f --- /dev/null +++ b/fj-core/src/main/resources/core/xml/remove_whitespace_nodes.xslt @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/xml/TestTransformerXML.java b/fj-core/src/test/java/test/org/fugerit/java/core/xml/TestTransformerXML.java index 89184801..faf72b8e 100644 --- a/fj-core/src/test/java/test/org/fugerit/java/core/xml/TestTransformerXML.java +++ b/fj-core/src/test/java/test/org/fugerit/java/core/xml/TestTransformerXML.java @@ -10,6 +10,7 @@ import org.fugerit.java.core.cfg.ConfigRuntimeException; import org.fugerit.java.core.lang.helpers.BooleanUtils; +import org.fugerit.java.core.xml.TransformerConfig; import org.fugerit.java.core.xml.TransformerXML; import org.junit.Assert; import org.junit.Test; @@ -67,6 +68,19 @@ public void newTransformer() { Assert.assertTrue( ok ); } + @Test + public void newTransformerConfig() { + boolean ok = false; + try { + Transformer transformer = TransformerXML.newTransformerWithConfig( TransformerConfig.newIndentConfig(null) ); + log.info( "factory -> {}", transformer ); + ok = transformer != null; + } catch (Exception e) { + this.failEx(e); + } + Assert.assertTrue( ok ); + } + @Test public void newTransformerSource() { boolean ok = false; diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/xml/dom/TestDOMClean.java b/fj-core/src/test/java/test/org/fugerit/java/core/xml/dom/TestDOMClean.java new file mode 100644 index 00000000..bedb40e0 --- /dev/null +++ b/fj-core/src/test/java/test/org/fugerit/java/core/xml/dom/TestDOMClean.java @@ -0,0 +1,62 @@ +package test.org.fugerit.java.core.xml.dom; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; + +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.core.xml.TransformerConfig; +import org.fugerit.java.core.xml.XMLException; +import org.fugerit.java.core.xml.XMLWhiteSpaceRemove; +import org.fugerit.java.core.xml.dom.DOMIO; +import org.junit.Assert; +import org.junit.Test; +import org.w3c.dom.Document; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TestDOMClean { + + private static final String INPUT_FILE_XML = "dom_clean1.xml"; + + private void testWorker( String testFile, File outFile, TransformerConfig config) throws IOException, XMLException { + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "core/xml/dom/"+testFile ); + Writer writer = new FileWriter( outFile ) ) { + Document doc = DOMIO.loadDOMDoc( is ); + config.stream().forEach( e -> log.info( "outputProperty {} -> {}", e.getKey(), e.getValue() ) ); + XMLWhiteSpaceRemove.cleanBlankNodes(doc, writer, TransformerConfig.newIndentConfig( 5 )); + } + } + + @Test + public void testClean1() throws IOException, XMLException { + String testFile = INPUT_FILE_XML; + File outFile = new File( "target", "cleaned_a_"+testFile ); + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "core/xml/dom/"+testFile ); + Writer writer = new FileWriter( outFile ) ) { + Document doc = DOMIO.loadDOMDoc( is ); + XMLWhiteSpaceRemove.cleanBlankNodesIndent2(doc, writer); + } + Assert.assertTrue( outFile.exists() ); + } + + @Test + public void testClean2() throws IOException, XMLException { + String testFile = "dom_clean1.xml"; + File outFile = new File( "target", "cleaned_b_"+testFile ); + this.testWorker(testFile, outFile, TransformerConfig.newIndentConfig( 5 )); + Assert.assertTrue( outFile.exists() ); + } + + @Test + public void testClean3() throws IOException, XMLException { + String testFile = "dom_clean1.xml"; + File outFile = new File( "target", "cleaned_c_"+testFile ); + this.testWorker(testFile, outFile, TransformerConfig.newConfig().indentNo().omitXmlDeclarationNo()); + Assert.assertTrue( outFile.exists() ); + } + +} diff --git a/fj-core/src/test/resources/core/xml/dom/dom_clean1.xml b/fj-core/src/test/resources/core/xml/dom/dom_clean1.xml new file mode 100644 index 00000000..6d0af0a4 --- /dev/null +++ b/fj-core/src/test/resources/core/xml/dom/dom_clean1.xml @@ -0,0 +1,27 @@ + + + + + field21 + + + sec_41_Testlabelwith + + + + + field22 + + + sec_42_Testlabel2 + + + + + field23 + + + sec_42_Testlabel4 + + +