Skip to content

Commit 0702a6e

Browse files
committed
[feature] fn:transform post-process function
Read the post-process parameter, and if it is supplied and is a function, apply it to the output of the transformation as a final step in generating the output of fn:transform. The post-process function is applied possibly multiple times, once to the main output and once to every secondary output document. The final result is a map with the same keys as before post processing, but with post processed transformed values replacing transformed values.
1 parent f2bddb9 commit 0702a6e

File tree

3 files changed

+69
-7
lines changed

3 files changed

+69
-7
lines changed

exist-core/src/main/java/org/exist/xquery/functions/fn/FnTransform.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.evolvedbinary.j8fu.tuple.Tuple2;
2626
import com.github.benmanes.caffeine.cache.Cache;
2727
import com.github.benmanes.caffeine.cache.Caffeine;
28+
import com.github.krukow.clj_lang.PersistentTreeMap;
2829
import io.lacuna.bifurcan.IEntry;
2930
import net.jpountz.xxhash.XXHash64;
3031
import net.jpountz.xxhash.XXHashFactory;
@@ -516,12 +517,13 @@ private MapType makeResultMap(final Options options, final Delivery delivery, fi
516517
outputKey = new StringValue("output");
517518
}
518519

519-
final Sequence primaryValue = convertToDeliveryFormat(options, delivery);
520+
final Sequence primaryValue = postProcess(outputKey, convertToDeliveryFormat(options, delivery), options.postProcess);
520521
outputMap.add(outputKey, primaryValue);
521522

522523
for (final Map.Entry<URI, Delivery> resultDocument : resultDocuments.entrySet()) {
523-
final Sequence value = convertToDeliveryFormat(options, resultDocument.getValue());
524-
outputMap.add(new AnyURIValue(resultDocument.getKey()), value);
524+
final AnyURIValue key = new AnyURIValue(resultDocument.getKey());
525+
final Sequence value = postProcess(key, convertToDeliveryFormat(options, resultDocument.getValue()), options.postProcess);
526+
outputMap.add(key, value);
525527
}
526528

527529
return outputMap;
@@ -537,16 +539,26 @@ private MapType makeResultMap(final Options options, final Sequence rawPrimaryOu
537539
outputKey = new StringValue("output");
538540
}
539541

540-
outputMap.add(outputKey, rawPrimaryOutput);
542+
outputMap.add(outputKey, postProcess(outputKey, rawPrimaryOutput, options.postProcess));
541543

542544
for (final Map.Entry<URI, Delivery> resultDocument : resultDocuments.entrySet()) {
543-
final Sequence value = convertToDeliveryFormat(options, resultDocument.getValue());
544-
outputMap.add(new AnyURIValue(resultDocument.getKey()), value);
545+
final AnyURIValue key = new AnyURIValue(resultDocument.getKey());
546+
final Sequence value = postProcess(key, convertToDeliveryFormat(options, resultDocument.getValue()), options.postProcess);
547+
outputMap.add(key, value);
545548
}
546549

547550
return outputMap;
548551
}
549552

553+
private Sequence postProcess(final AtomicValue key, final Sequence before, final Optional<FunctionReference> postProcessingFunction) throws XPathException {
554+
if (postProcessingFunction.isPresent()) {
555+
FunctionReference functionReference = postProcessingFunction.get();
556+
return functionReference.evalFunction(null, null, new Sequence[]{key, before});
557+
} else {
558+
return before;
559+
}
560+
}
561+
550562
private Sequence convertToDeliveryFormat(final Options options, final Delivery delivery) throws XPathException {
551563

552564
switch (options.deliveryFormat) {
@@ -1041,6 +1053,8 @@ private Map<net.sf.saxon.s9api.QName, XdmValue> readParamsMap(final Optional<Map
10411053
final Optional<Long> sourceTextChecksum;
10421054
final String stylesheetNodeDocumentPath;
10431055

1056+
final Optional<FunctionReference> postProcess;
1057+
10441058
Options(final MapType options) throws XPathException {
10451059
xsltSource = getStylesheet(options);
10461060

@@ -1107,6 +1121,8 @@ private Map<net.sf.saxon.s9api.QName, XdmValue> readParamsMap(final Optional<Map
11071121
serializationParams = FnTransform.SERIALIZATION_PARAMS.get(xsltVersion, options);
11081122

11091123
validateRequestedProperties(FnTransform.REQUESTED_PROPERTIES.get(xsltVersion, options).orElse(new MapType(context)));
1124+
1125+
postProcess = FnTransform.POST_PROCESS.get(xsltVersion, options);
11101126
}
11111127

11121128
private DeliveryFormat getDeliveryFormat(final float xsltVersion, final MapType options) throws XPathException {

exist-core/src/test/java/xquery/xquery3/XQuery3Tests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
@RunWith(XSuite.class)
2828
@XSuite.XSuiteFiles({
2929
//"src/test/xquery/xquery3",
30-
"src/test/xquery/xquery3/fnTransformErr9.xqm"
30+
"src/test/xquery/xquery3/fnTransform79.xqm"
3131
})
3232
public class XQuery3Tests {
3333
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
(:
2+
: eXist-db Open Source Native XML Database
3+
: Copyright (C) 2001 The eXist-db Authors
4+
:
5+
6+
: http://www.exist-db.org
7+
:
8+
: This library is free software; you can redistribute it and/or
9+
: modify it under the terms of the GNU Lesser General Public
10+
: License as published by the Free Software Foundation; either
11+
: version 2.1 of the License, or (at your option) any later version.
12+
:
13+
: This library is distributed in the hope that it will be useful,
14+
: but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
: Lesser General Public License for more details.
17+
:
18+
: You should have received a copy of the GNU Lesser General Public
19+
: License along with this library; if not, write to the Free Software
20+
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
:)
22+
xquery version "3.1";
23+
24+
module namespace testTransform="http://exist-db.org/xquery/test/function_transform";
25+
26+
declare namespace test="http://exist-db.org/xquery/xqsuite";
27+
28+
declare variable $testTransform:transform-79-xsl :=
29+
"<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
30+
version='1.0'>
31+
<xsl:template match='/'>
32+
<out><xsl:copy-of select='.'/></out>
33+
</xsl:template>
34+
</xsl:stylesheet>";
35+
36+
declare
37+
%test:assertEquals("<b>89</b>")
38+
function testTransform:transform-79() {
39+
let $xsl := $testTransform:transform-79-xsl
40+
let $trans-result := fn:transform(map{"stylesheet-text":$xsl,
41+
"delivery-format" : "document",
42+
"source-node": parse-xml('<a><b>89</b></a>'),
43+
"post-process" : function($uri, $doc) { $doc/out/a/b }
44+
})
45+
return $trans-result("output")
46+
};

0 commit comments

Comments
 (0)