You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mu...@apache.org on 2025/03/27 12:22:14 UTC
(xalan-java) branch xalan-j_xslt3.0_mvn updated: improving implementation of xsl:result-document element by adding method='json' support, and adding few new working related test cases
This is an automated email from the ASF dual-hosted git repository.
mukulg pushed a commit to branch xalan-j_xslt3.0_mvn
in repository https://gitbox.apache.org/repos/asf/xalan-java.git
The following commit(s) were added to refs/heads/xalan-j_xslt3.0_mvn by this push:
new a9985837f improving implementation of xsl:result-document element by adding method='json' support, and adding few new working related test cases
a9985837f is described below
commit a9985837fd705120ac92f0d33388c21675b515a8
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Mar 27 17:51:31 2025 +0530
improving implementation of xsl:result-document element by adding method='json' support, and adding few new working related test cases
---
README | 6 +-
.../java/org/apache/xalan/templates/Constants.java | 10 ++-
.../apache/xalan/templates/ElemResultDocument.java | 22 ++++++
.../xalan/tests/util/XSLTransformTestsUtil.java | 40 ++++++++---
.../xalan/tests/xslt3/XslResultDocumentTests.java | 80 ++++++++++++++++++++--
.../xsl_result_document/gold/result1.json | 5 ++
.../xsl_result_document/gold/result2.json | 17 +++++
.../xsl_result_document/gold/result3.json | 22 ++++++
src/test/resources/xsl_result_document/map1.xml | 20 ++++++
src/test/resources/xsl_result_document/test3.xsl | 40 +++++++++++
src/test/resources/xsl_result_document/test4.xsl | 59 ++++++++++++++++
src/test/resources/xsl_result_document/test5.xsl | 58 ++++++++++++++++
12 files changed, 358 insertions(+), 21 deletions(-)
diff --git a/README b/README
index da6eb36e6..7f9b230ec 100644
--- a/README
+++ b/README
@@ -17,7 +17,7 @@
Copyright 1999-2025 The Apache Software Foundation
-Document last modified : 2025-03-25
+Document last modified : 2025-03-27
Authors:
Gary Gregory <gg...@apache.org>
@@ -59,11 +59,11 @@ This produces Maven build output with trailing information like following:
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.apache.xalan.tests.main.AllXsl3Tests
-[INFO] Tests run: 958, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.686 s - in org.apache.xalan.tests.main.AllXsl3Tests
+[INFO] Tests run: 961, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.153 s - in org.apache.xalan.tests.main.AllXsl3Tests
[INFO]
[INFO] Results:
[INFO]
-[INFO] Tests run: 958, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 961, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xalan/templates/Constants.java b/src/main/java/org/apache/xalan/templates/Constants.java
index 323ae3fc7..6d695559d 100644
--- a/src/main/java/org/apache/xalan/templates/Constants.java
+++ b/src/main/java/org/apache/xalan/templates/Constants.java
@@ -376,22 +376,26 @@ public class Constants extends org.apache.xml.utils.Constants
/** Mnemonics for the possible values of the xsl:output element's
* method= attribute:
* <ul>
- * <li>ATTRVAL_OUTPUT_METHOD_XML = Use an XML formatter to
+ * <li>ATTRVAL_OUTPUT_METHOD_XML: Use an XML formatter to
* produce the output document (basic XSLT operation).</li>
* <li>ATTRVAL_OUTPUT_METHOD_HTML: Use an HTML formatter to
* produce the output document. When generating HTML documents,
* this may yield better results; it does things like escaping
* characters in href attributes.</li>
- * </li>ATTRVAL_OUTPUT_METHOD_TEXT: Use a Text formatter to
+ * <li>ATTRVAL_OUTPUT_METHOD_TEXT: Use a Text formatter to
* produce the output document. Generally the right choice if your
* stylesheet wants to take over _all_ the details of formatting,
* most often when producing something that isn't an XML or HTML
* document.</li>
+ * <li>ATTRVAL_OUTPUT_METHOD_JSON: Use a JSON text formatter to
+ * produce the output document. Added for XSLT 3.0 spec
+ * implementation.</li>
* </ul>
* */
public static final String ATTRVAL_OUTPUT_METHOD_HTML = "html",
ATTRVAL_OUTPUT_METHOD_XML = "xml",
- ATTRVAL_OUTPUT_METHOD_TEXT = "text";
+ ATTRVAL_OUTPUT_METHOD_TEXT = "text",
+ ATTRVAL_OUTPUT_METHOD_JSON = "json";
/* For space-att*/
diff --git a/src/main/java/org/apache/xalan/templates/ElemResultDocument.java b/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
index 7c8b93671..6e5e15c5d 100644
--- a/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
+++ b/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
@@ -36,6 +36,8 @@ import org.apache.xpath.XPathContext;
import org.apache.xpath.objects.XNodeSet;
import org.apache.xpath.objects.XNodeSetForDOM;
import org.apache.xpath.objects.XRTreeFrag;
+import org.json.JSONException;
+import org.json.JSONObject;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -221,7 +223,27 @@ public class ElemResultDocument extends ElemTemplateElement
writeStringContentsToFile(hrefStr, textStrValue);
}
+ else if ((Constants.ATTRVAL_OUTPUT_METHOD_JSON).equals(methodQname.toString())) {
+ String jsonStrValue = transformer.transformToString(this);
+
+ try {
+ // Verify that, the string value represents a legible JSON
+ // document.
+ JSONObject jsonObject = new JSONObject(jsonStrValue);
+ }
+ catch (JSONException ex) {
+ throw new TransformerException("XPTY0004 : An xsl:result-document instruction within a stylesheet has attribute "
+ + "\"method\" with value 'json'. There was a JSON syntax error in "
+ + "an input string or there was a duplicate object key. Following "
+ + "run-time error occured : " + ex.getMessage() + ".", srcLocator);
+ }
+
+ writeStringContentsToFile(hrefStr, jsonStrValue.trim());
+ }
}
+ catch (TransformerException ex) {
+ throw ex;
+ }
catch (Exception ex) {
throw new TransformerException("XPTY0004 : An exception occured while evaluating an "
+ "xsl:result-document instruction. Following "
diff --git a/src/test/java/org/apache/xalan/tests/util/XSLTransformTestsUtil.java b/src/test/java/org/apache/xalan/tests/util/XSLTransformTestsUtil.java
index 7d057a0ae..654198998 100644
--- a/src/test/java/org/apache/xalan/tests/util/XSLTransformTestsUtil.java
+++ b/src/test/java/org/apache/xalan/tests/util/XSLTransformTestsUtil.java
@@ -195,11 +195,11 @@ public class XSLTransformTestsUtil {
*/
protected void runXslTransformAndAssertOutput(String xmlFilePath, String xslFilePath,
String[] goldFileStrArr, String[] goldFileNameArr,
- XslTestsErrorHandler xslTransformErrHandler) {
-
- String fileProducedName1 = goldFileNameArr[0];
- String fileProducedName2 = goldFileNameArr[1];
+ XslTestsErrorHandler xslTransformErrHandler) {
+ String fileProducedName1 = null;
+ String fileProducedName2 = null;
+
try {
String xmlDocumentUriStr = ((new File(xmlFilePath)).toURI()).toString();
String xslDocumentUriStr = ((new File(xslFilePath)).toURI()).toString();
@@ -220,12 +220,28 @@ public class XSLTransformTestsUtil {
transformer.transform(xmlDomSrc, new StreamResult(resultStrWriter));
- String fileProducedStr1 = getFileContentAsString(fileProducedName1);
- String fileProducedStr2 = getFileContentAsString(fileProducedName2);
-
- if (!(goldFileStrArr[0].equals(fileProducedStr1) && goldFileStrArr[1].equals(fileProducedStr2))) {
- Assert.fail();
- }
+ if (goldFileNameArr.length == 2) {
+ fileProducedName1 = goldFileNameArr[0];
+ fileProducedName2 = goldFileNameArr[1];
+
+ String fileProducedStr1 = getFileContentAsString(fileProducedName1);
+ String fileProducedStr2 = getFileContentAsString(fileProducedName2);
+
+ if (!(goldFileStrArr[0].equals(fileProducedStr1) && goldFileStrArr[1].equals(fileProducedStr2))) {
+ Assert.fail();
+ }
+ }
+ else {
+ // Only one file is there to compare it's contents
+
+ fileProducedName1 = goldFileNameArr[0];
+
+ String fileProducedStr1 = getFileContentAsString(fileProducedName1);
+
+ if (!(goldFileStrArr[0].equals(fileProducedStr1))) {
+ Assert.fail();
+ }
+ }
}
catch (Exception ex) {
Assert.fail();
@@ -234,7 +250,9 @@ public class XSLTransformTestsUtil {
// These statements delete the temporary files
// produced while running a test case using this method.
(new File(fileProducedName1)).delete();
- (new File(fileProducedName2)).delete();
+ if (fileProducedName2 != null) {
+ (new File(fileProducedName2)).delete();
+ }
}
}
diff --git a/src/test/java/org/apache/xalan/tests/xslt3/XslResultDocumentTests.java b/src/test/java/org/apache/xalan/tests/xslt3/XslResultDocumentTests.java
index a64099bac..c34df5f17 100644
--- a/src/test/java/org/apache/xalan/tests/xslt3/XslResultDocumentTests.java
+++ b/src/test/java/org/apache/xalan/tests/xslt3/XslResultDocumentTests.java
@@ -63,8 +63,8 @@ public class XslResultDocumentTests extends XSLTransformTestsUtil {
String goldFileContentStr1 = getFileContentAsString(goldFilePath1);
String goldFileContentStr2 = getFileContentAsString(goldFilePath2);
- String[] goldFileStrArr = new String[] {goldFileContentStr1, goldFileContentStr2};
- String[] goldFileNameArr = new String[] {goldFileName1, goldFileName2};
+ String[] goldFileStrArr = new String[] { goldFileContentStr1, goldFileContentStr2 };
+ String[] goldFileNameArr = new String[] { goldFileName1, goldFileName2 };
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFileStrArr,
goldFileNameArr, null);
@@ -89,8 +89,80 @@ public class XslResultDocumentTests extends XSLTransformTestsUtil {
String goldFileContentStr1 = getFileContentAsString(goldFilePath1);
String goldFileContentStr2 = getFileContentAsString(goldFilePath2);
- String[] goldFileStrArr = new String[] {goldFileContentStr1, goldFileContentStr2};
- String[] goldFileNameArr = new String[] {goldFileName1, goldFileName2};
+ String[] goldFileStrArr = new String[] { goldFileContentStr1, goldFileContentStr2 };
+ String[] goldFileNameArr = new String[] { goldFileName1, goldFileName2 };
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFileStrArr,
+ goldFileNameArr, null);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Test
+ public void xslResultDocumentTest3() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+
+ String goldFileName1 = "result1.json";
+
+ String goldFilePath1 = XSL_TRANSFORM_GOLD_DIRPATH + goldFileName1;
+
+
+ try {
+ String goldFileContentStr1 = getFileContentAsString(goldFilePath1);
+
+ String[] goldFileStrArr = new String[] { goldFileContentStr1 };
+ String[] goldFileNameArr = new String[] { goldFileName1 };
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFileStrArr,
+ goldFileNameArr, null);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Test
+ public void xslResultDocumentTest4() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+
+ String goldFileName1 = "result2.json";
+
+ String goldFilePath1 = XSL_TRANSFORM_GOLD_DIRPATH + goldFileName1;
+
+
+ try {
+ String goldFileContentStr1 = getFileContentAsString(goldFilePath1);
+
+ String[] goldFileStrArr = new String[] { goldFileContentStr1 };
+ String[] goldFileNameArr = new String[] { goldFileName1 };
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFileStrArr,
+ goldFileNameArr, null);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Test
+ public void xslResultDocumentTest5() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+
+ String goldFileName1 = "result3.json";
+
+ String goldFilePath1 = XSL_TRANSFORM_GOLD_DIRPATH + goldFileName1;
+
+
+ try {
+ String goldFileContentStr1 = getFileContentAsString(goldFilePath1);
+
+ String[] goldFileStrArr = new String[] { goldFileContentStr1 };
+ String[] goldFileNameArr = new String[] { goldFileName1 };
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFileStrArr,
goldFileNameArr, null);
diff --git a/src/test/resources/xsl_result_document/gold/result1.json b/src/test/resources/xsl_result_document/gold/result1.json
new file mode 100644
index 000000000..8b4c8f02e
--- /dev/null
+++ b/src/test/resources/xsl_result_document/gold/result1.json
@@ -0,0 +1,5 @@
+{
+ "a" : 1,
+ "b" : 2,
+ "c" : 3
+ }
\ No newline at end of file
diff --git a/src/test/resources/xsl_result_document/gold/result2.json b/src/test/resources/xsl_result_document/gold/result2.json
new file mode 100644
index 000000000..15f4a99a9
--- /dev/null
+++ b/src/test/resources/xsl_result_document/gold/result2.json
@@ -0,0 +1,17 @@
+{"data": [
+ {
+ "a": 1,
+ "b": 2,
+ "c": 3
+ },
+ {
+ "m": 4,
+ "n": 5,
+ "o": 6
+ },
+ {
+ "p": 7,
+ "q": 8,
+ "r": 9
+ }
+]}
\ No newline at end of file
diff --git a/src/test/resources/xsl_result_document/gold/result3.json b/src/test/resources/xsl_result_document/gold/result3.json
new file mode 100644
index 000000000..16beaa99e
--- /dev/null
+++ b/src/test/resources/xsl_result_document/gold/result3.json
@@ -0,0 +1,22 @@
+{"data": [
+ {
+ "a": 1,
+ "b": 2,
+ "c": 3
+ },
+ {
+ "m": 4,
+ "n": 5,
+ "o": 6
+ },
+ {
+ "p": 7,
+ "q": 8,
+ "r": 9
+ },
+ {
+ "z1": 12,
+ "y1": 11,
+ "x1": 10
+ }
+]}
\ No newline at end of file
diff --git a/src/test/resources/xsl_result_document/map1.xml b/src/test/resources/xsl_result_document/map1.xml
new file mode 100644
index 000000000..bb554e0ef
--- /dev/null
+++ b/src/test/resources/xsl_result_document/map1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map xmlns="http://www.w3.org/2005/xpath-functions">
+ <array key="data">
+ <map>
+ <number key="a">1</number>
+ <number key="b">2</number>
+ <number key="c">3</number>
+ </map>
+ <map>
+ <number key="m">4</number>
+ <number key="n">5</number>
+ <number key="o">6</number>
+ </map>
+ <map>
+ <number key="p">7</number>
+ <number key="q">8</number>
+ <number key="r">9</number>
+ </map>
+ </array>
+</map>
\ No newline at end of file
diff --git a/src/test/resources/xsl_result_document/test3.xsl b/src/test/resources/xsl_result_document/test3.xsl
new file mode 100644
index 000000000..0d04a9d50
--- /dev/null
+++ b/src/test/resources/xsl_result_document/test3.xsl
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSL 3 stylesheet test case, to test xsl:result-document
+ instruction having method="json". -->
+
+ <xsl:output method="text"/>
+
+ <xsl:template match="/">
+ <xsl:result-document href="result1.json" method="json">
+ {
+ "a" : 1,
+ "b" : 2,
+ "c" : 3
+ }
+ </xsl:result-document>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
diff --git a/src/test/resources/xsl_result_document/test4.xsl b/src/test/resources/xsl_result_document/test4.xsl
new file mode 100644
index 000000000..4719349ba
--- /dev/null
+++ b/src/test/resources/xsl_result_document/test4.xsl
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ exclude-result-prefixes="fn"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSL 3 stylesheet test case, to test xsl:result-document
+ instruction having method="json". -->
+
+ <xsl:output method="text"/>
+
+ <xsl:template match="/">
+ <xsl:result-document href="result2.json" method="json">
+ <xsl:variable name="xmlNodeSet1">
+ <fn:map>
+ <fn:array key="data">
+ <fn:map>
+ <fn:number key="a">1</fn:number>
+ <fn:number key="b">2</fn:number>
+ <fn:number key="c">3</fn:number>
+ </fn:map>
+ <fn:map>
+ <fn:number key="m">4</fn:number>
+ <fn:number key="n">5</fn:number>
+ <fn:number key="o">6</fn:number>
+ </fn:map>
+ <fn:map>
+ <fn:number key="p">7</fn:number>
+ <fn:number key="q">8</fn:number>
+ <fn:number key="r">9</fn:number>
+ </fn:map>
+ </fn:array>
+ </fn:map>
+ </xsl:variable>
+ <xsl:value-of select="xml-to-json($xmlNodeSet1, map {'indent' : true()})"/>
+ </xsl:result-document>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
diff --git a/src/test/resources/xsl_result_document/test5.xsl b/src/test/resources/xsl_result_document/test5.xsl
new file mode 100644
index 000000000..480bbe27e
--- /dev/null
+++ b/src/test/resources/xsl_result_document/test5.xsl
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ exclude-result-prefixes="fn"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSL 3 stylesheet test case, to test xsl:result-document
+ instruction having method="json". -->
+
+ <xsl:output method="text"/>
+
+ <xsl:template match="/">
+ <xsl:variable name="xmlMapNode1" select="doc('map1.xml')"/>
+ <xsl:result-document href="result3.json" method="json">
+ <xsl:variable name="xmlNodeSet1">
+ <xsl:apply-templates select="$xmlMapNode1/fn:map"/>
+ </xsl:variable>
+ <xsl:value-of select="xml-to-json($xmlNodeSet1, map {'indent' : true()})"/>
+ </xsl:result-document>
+ </xsl:template>
+
+ <!-- This stylesheet template, appends more XML structure information to the
+ original XML element node matched by this template. -->
+ <xsl:template match="fn:map">
+ <xsl:copy>
+ <fn:array>
+ <xsl:copy-of select="fn:array/@*"/>
+ <xsl:copy-of select="fn:array/*"/>
+ <fn:map>
+ <fn:number key="x1">10</fn:number>
+ <fn:number key="y1">11</fn:number>
+ <fn:number key="z1">12</fn:number>
+ </fn:map>
+ </fn:array>
+ </xsl:copy>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org