Skip to content

Commit

Permalink
Merge pull request #469 from lankavitharana/addXsltParamSupport
Browse files Browse the repository at this point in the history
Add parameter passing support for xslt transformations
  • Loading branch information
Bhashinee committed May 14, 2024
2 parents 340fcbd + 69bd69d commit fe7bb90
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 6 deletions.
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "xslt"
version = "2.6.0"
version = "2.6.1"
authors = ["Ballerina"]
keywords = ["xslt", "xml", "html", "xsl", "transformation"]
repository = "https://github.com/ballerina-platform/module-ballerina-xslt"
Expand All @@ -15,8 +15,8 @@ graalvmCompatible = true
[[platform.java17.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "xslt-native"
version = "2.6.0"
path = "../native/build/libs/xslt-native-2.6.0.jar"
version = "2.6.1"
path = "../native/build/libs/xslt-native-2.6.1-SNAPSHOT.jar"

[[platform.java17.dependency]]
path = "./lib/jakarta.activation-1.2.2.jar"
Expand Down
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ modules = [
[[package]]
org = "ballerina"
name = "xslt"
version = "2.6.0"
version = "2.6.1"
dependencies = [
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"},
Expand Down
3 changes: 2 additions & 1 deletion ballerina/natives.bal
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import ballerina/jballerina.java;
#
# + input - An XML object, which needs to be transformed
# + xsl - The XSL style sheet represented in an XML object
# + params - Optional parameters passed into the xslt template
# + return - The transformed result represented in an XML object or else an `error` if the given `XML` object
# cannot be transformed
public isolated function transform(xml input, xml xsl) returns xml|error = @java:Method {
public isolated function transform(xml input, xml xsl, map<string|decimal> params = {}) returns xml|error = @java:Method {
'class: "io.ballerina.stdlib.xslt.XsltTransformer"
} external;
18 changes: 18 additions & 0 deletions ballerina/tests/read-from-file.bal
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ function testReadFromFile() {
}
}

@test:Config {}
function testReadFromFileWithParams() returns error? {
string xmlFilePath = "tests/resources/datafiles/cd_catalog.xml";
string xslFilePath = "tests/resources/datafiles/cd_catalog_with_params.xsl";
string strParam = "Music CD Collection With Artist";
decimal intParam = 5;
map<string|decimal> params = {"param1":strParam, "param2": intParam};
xml result = check readFromFileWithParams(xmlFilePath, xslFilePath, params);
xml expected = check readXml("tests/resources/datafiles/read_from_file_with_params_result.xml");
test:assertEquals(result, expected);
}

function readFromFileWithParams(string xmlFilePath, string xslFilePath, map<string|decimal> params) returns xml|error {
xml xmlValue = check readXml(xmlFilePath);
xml xslValue = check readXml(xslFilePath);
return transform(xmlValue, xslValue, params);
}

@test:Config {
enable: false
}
Expand Down
27 changes: 27 additions & 0 deletions ballerina/tests/resources/datafiles/cd_catalog_with_params.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="param1"></xsl:param>
<xsl:param name="param2"></xsl:param>
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<h3>
<xsl:value-of select="$param1"/>
</h3>
<h4>My Rating - <xsl:value-of select="$param2"/></h4>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Title</th>
<th style="text-align:left">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<html>
<body>
<h2>My CD Collection</h2>
<h3>Music CD Collection With Artist</h3>
<h4>My Rating - 5</h4>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Title</th>
<th style="text-align:left">Artist</th>
</tr>
<tr>
<td>Empire Burlesque</td>
<td>Bob Dylan</td>
</tr>
<tr>
<td>Hide your heart</td>
<td>Bonnie Tyler</td>
</tr>
<tr>
<td>Greatest Hits</td>
<td>Dolly Parton</td>
</tr>
<tr>
<td>Still got the blues</td>
<td>Gary Moore</td>
</tr>
</table>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import io.ballerina.runtime.api.types.XmlNodeType;
import io.ballerina.runtime.api.utils.StringUtils;
import io.ballerina.runtime.api.utils.XmlUtils;
import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BError;
import io.ballerina.runtime.api.values.BIterator;
import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BString;
import io.ballerina.runtime.api.values.BXml;
import io.ballerina.runtime.api.values.BXmlItem;
import io.ballerina.runtime.api.values.BXmlSequence;
Expand Down Expand Up @@ -56,7 +60,7 @@ public class XsltTransformer {
private static final PrintStream errStream = System.err;
private static final String OPERATION = "Failed to perform XSL transformation: ";

public static Object transform(BXml xmlInput, BXml xslInput) {
public static Object transform(BXml xmlInput, BXml xslInput, BMap<BString, Object> paramInput) {

try {
boolean unwrap = false;
Expand All @@ -83,6 +87,7 @@ public static Object transform(BXml xmlInput, BXml xslInput) {

Transformer transformer = new BasicTransformerFactory().newInstance().newTransformer(xslSource);
transformer.setOutputProperty("omit-xml-declaration", "yes");
applyParameters(transformer, paramInput);
transformer.transform(xmlSource, streamResult);

String resultStr = stringWriter.getBuffer().toString().trim();
Expand All @@ -104,6 +109,28 @@ public static Object transform(BXml xmlInput, BXml xslInput) {
}
}

/**
* Apply template parameters to the transformer.
*
* @param transformer The transformer to be used
* @param paramInput The input parameter map
*/
private static void applyParameters(Transformer transformer, BMap<BString, Object> paramInput) {
BIterator<?> iterator = paramInput.getIterator();
while (iterator.hasNext()) {
BArray next = (BArray) iterator.next();
BString key = (BString) next.get(0);
Object value = next.get(1);
// Note that you can add any value as long as toString method of that value works properly,
// Only support string and int at the moment, may be able to improve the logic to support
// xml as well, but current XmlItem ballerina runtime value toString method does not return
// the value expected by the transformer, so not supporting that at the moment
// And here, no need to check the types of the values as the compiler will make sure
// only viable types of values will arrive here
transformer.setParameter(key.getValue(), value);
}
}

/**
* Converts the given string to a BXmlSequence object.
*
Expand Down

0 comments on commit fe7bb90

Please sign in to comment.