diff --git a/src/it/groovy/README.md b/src/it/groovy/README.md
new file mode 100644
index 0000000..eff85a9
--- /dev/null
+++ b/src/it/groovy/README.md
@@ -0,0 +1,12 @@
+# Groovy Integration Test
+
+This module contains integration tests for `jcabi-xml` usage in Groovy scripts.
+
+To run the tests, execute the following command:
+
+```shell
+mvn clean integration-test invoker:run -Dinvoker.test=groovy -DskipTests
+```
+
+The testing Groovy code you can find in the [verify.groovy](verify.groovy)
+script.
\ No newline at end of file
diff --git a/src/it/groovy/first.xmir b/src/it/groovy/first.xmir
new file mode 100644
index 0000000..f692288
--- /dev/null
+++ b/src/it/groovy/first.xmir
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/it/groovy/invoker.properties b/src/it/groovy/invoker.properties
new file mode 100644
index 0000000..2329e6c
--- /dev/null
+++ b/src/it/groovy/invoker.properties
@@ -0,0 +1 @@
+invoker.goals = clean
\ No newline at end of file
diff --git a/src/it/groovy/pom.xml b/src/it/groovy/pom.xml
new file mode 100644
index 0000000..774df8a
--- /dev/null
+++ b/src/it/groovy/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+ 4.0.0
+
+ com.jcabi
+ jcabi
+ 1.39.0
+
+ com.jcabi.xml
+ groovy
+ 1.0-SNAPSHOT
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
diff --git a/src/it/groovy/same.xmir b/src/it/groovy/same.xmir
new file mode 100644
index 0000000..950c93f
--- /dev/null
+++ b/src/it/groovy/same.xmir
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/it/groovy/verify.groovy b/src/it/groovy/verify.groovy
new file mode 100644
index 0000000..8eb2ed6
--- /dev/null
+++ b/src/it/groovy/verify.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012-2022, jcabi.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met: 1) Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer. 2) Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution. 3) Neither the name of the jcabi.com nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+ * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import com.jcabi.xml.XMLDocument
+
+def log = new File(basedir, 'build.log')
+def fist = new XMLDocument(new File(basedir, 'first.xmir'))
+def same = new XMLDocument(new File(basedir, 'same.xmir'))
+
+assert fist.equals(same)
+
+assert log.text.contains("BUILD SUCCESS")
\ No newline at end of file
diff --git a/src/main/java/com/jcabi/xml/XMLDocument.java b/src/main/java/com/jcabi/xml/XMLDocument.java
index e5b14d1..fa16c27 100644
--- a/src/main/java/com/jcabi/xml/XMLDocument.java
+++ b/src/main/java/com/jcabi/xml/XMLDocument.java
@@ -115,6 +115,11 @@ public final class XMLDocument implements XML {
*/
private final transient Node cache;
+ /**
+ * Transformer factory to use for {@link #toString()}.
+ */
+ private final transient TransformerFactory tfactory;
+
static {
if (XMLDocument.DFACTORY.getClass().getName().contains("xerces")) {
try {
@@ -155,6 +160,34 @@ public XMLDocument(final String text) {
);
}
+ /**
+ * Public ctor, from XML as a text.
+ *
+ * The object is created with a default implementation of
+ * {@link NamespaceContext}, which already defines a
+ * number of namespaces, for convenience, including:
+ *
+ *
xhtml: http://www.w3.org/1999/xhtml
+ * xs: http://www.w3.org/2001/XMLSchema
+ * xsi: http://www.w3.org/2001/XMLSchema-instance
+ * xsl: http://www.w3.org/1999/XSL/Transform
+ * svg: http://www.w3.org/2000/svg
+ *
+ * In future versions we will add more namespaces (submit a ticket if
+ * you need more of them defined here).
+ *
+ * @param text XML document body
+ * @param factory Transformer factory
+ */
+ public XMLDocument(final String text, final TransformerFactory factory) {
+ this(
+ new DomParser(XMLDocument.DFACTORY, text).document(),
+ new XPathContext(),
+ false,
+ factory
+ );
+ }
+
/**
* Public ctor, from XML as a text.
*
@@ -307,16 +340,37 @@ public XMLDocument(final InputStream stream) throws IOException {
* @param ctx Namespace context
* @param lfe Is it a leaf node?
*/
- private XMLDocument(final Node node, final XPathContext ctx,
- final boolean lfe) {
- this.context = ctx;
- this.leaf = lfe;
- this.cache = node;
+ private XMLDocument(
+ final Node node,
+ final XPathContext ctx,
+ final boolean lfe
+ ) {
+ this(node, ctx, lfe, XMLDocument.TFACTORY);
+ }
+
+ /**
+ * Private ctor.
+ * @param cache The source
+ * @param context Namespace context
+ * @param leaf Is it a leaf node?
+ * @param tfactory Transformer factory
+ * @checkstyle ParameterNumberCheck (5 lines)
+ */
+ public XMLDocument(
+ final Node cache,
+ final XPathContext context,
+ final boolean leaf,
+ final TransformerFactory tfactory
+ ) {
+ this.context = context;
+ this.leaf = leaf;
+ this.cache = cache;
+ this.tfactory = tfactory;
}
@Override
public String toString() {
- return XMLDocument.asString(this.cache);
+ return this.asString(this.cache);
}
@Override
@@ -505,18 +559,18 @@ private T fetch(final String query, final Class type)
* @param node The DOM node.
* @return String representation
*/
- private static String asString(final Node node) {
+ private String asString(final Node node) {
final StringWriter writer = new StringWriter();
final Transformer trans;
try {
synchronized (XMLDocument.class) {
- trans = XMLDocument.TFACTORY.newTransformer();
+ trans = this.tfactory.newTransformer();
}
} catch (final TransformerConfigurationException ex) {
throw new IllegalArgumentException(
String.format(
"Failed to create transformer by %s",
- XMLDocument.TFACTORY.getClass().getName()
+ this.tfactory.getClass().getName()
),
ex
);
diff --git a/src/test/java/com/jcabi/xml/XMLDocumentTest.java b/src/test/java/com/jcabi/xml/XMLDocumentTest.java
index d5395bb..43a3386 100644
--- a/src/test/java/com/jcabi/xml/XMLDocumentTest.java
+++ b/src/test/java/com/jcabi/xml/XMLDocumentTest.java
@@ -40,6 +40,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.xml.transform.TransformerFactory;
import org.apache.commons.lang3.StringUtils;
import org.cactoos.io.ResourceOf;
import org.cactoos.io.TeeInput;
@@ -48,6 +49,7 @@
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsEqual;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -381,6 +383,27 @@ void comparesToAnotherDocument() {
);
}
+ @Test
+ @Disabled
+ void comparesDocumentsWithDifferentIndentations() {
+ // @checkstyle MethodBodyCommentsCheck (4 lines)
+ // @todo #1:90min Implement comparison of XML documents with different indentations.
+ // The current implementation of XMLDocument does not ignore different indentations
+ // when comparing two XML documents. We need to implement a comparison that ignores
+ // different indentations. Don't forget to remove the @Disabled annotation from this test.
+ final TransformerFactory factory = TransformerFactory.newInstance(
+ "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl",
+ Thread.currentThread().getContextClassLoader()
+ );
+ MatcherAssert.assertThat(
+ "Different indentations should be ignored",
+ new XMLDocument("\n \n", factory),
+ Matchers.equalTo(
+ new XMLDocument("\n \n\n", factory)
+ )
+ );
+ }
+
@Test
void preservesXmlNamespaces() {
final String xml = "";