Skip to content

Commit 329bcf7

Browse files
authored
Merge pull request #4893 from evolvedbinary/6.x.x/hotfix/eb-4609-transform-globals
[6.x.x] Fix missing fn:transform global parameters
2 parents 1b8bb9a + 7a0b555 commit 329bcf7

File tree

4 files changed

+211
-7
lines changed

4 files changed

+211
-7
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.sf.saxon.s9api.XdmValue;
3333
import org.apache.commons.lang3.StringUtils;
3434
import org.exist.dom.memtree.NamespaceNode;
35+
import org.exist.dom.persistent.NodeProxy;
3536
import org.exist.security.PermissionDeniedException;
3637
import org.exist.xquery.ErrorCodes;
3738
import org.exist.xquery.XPathException;
@@ -527,7 +528,12 @@ private Source resolvePossibleStylesheetLocation(final String location) throws X
527528
"Can not access '" + location + "'" + e.getMessage());
528529
}
529530
if (document != null && document.hasOne() && Type.subTypeOf(document.getItemType(), Type.NODE)) {
530-
return new DOMSource((Node) document.itemAt(0));
531+
if (document instanceof NodeProxy proxy) {
532+
return new DOMSource(proxy.getNode());
533+
}
534+
else if (document.itemAt(0) instanceof Node node) {
535+
return new DOMSource(node);
536+
}
531537
}
532538
throw new XPathException(fnTransform, ErrorCodes.FODC0002,
533539
"Location '"+ location + "' returns an item which is not a document node");

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.apache.logging.log4j.LogManager;
3535
import org.apache.logging.log4j.Logger;
3636
import org.exist.dom.QName;
37-
import org.exist.dom.memtree.DocumentImpl;
3837
import org.exist.util.Holder;
3938
import org.exist.xquery.ErrorCodes;
4039
import org.exist.xquery.XPathException;
@@ -177,7 +176,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
177176
final Document document;
178177
Source source = sourceNode.get();
179178
final Node node = ((DOMSource)sourceNode.get()).getNode();
180-
if (!(node instanceof DocumentImpl)) {
179+
if (!(node instanceof org.exist.dom.memtree.DocumentImpl) && !(node instanceof org.exist.dom.persistent.DocumentImpl)) {
181180
//The source may not be a document
182181
//If it isn't, it should be part of a document, so we build a DOMSource to use
183182
document = node.getOwnerDocument();
@@ -193,7 +192,6 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
193192
final Transform.TemplateInvocation invocation = new Transform.TemplateInvocation(
194193
options, sourceNode, delivery, xslt30Transformer, resultDocuments);
195194
return invocation.invoke();
196-
197195
} catch (final SaxonApiException | UncheckedXPathException e) {
198196
throw originalXPathException("Could not transform input: ", e, ErrorCodes.FOXT0003);
199197
}
@@ -205,6 +203,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
205203

206204

207205
private XsltExecutable compileExecutable(final Options options) throws XPathException {
206+
208207
final XsltCompiler xsltCompiler = org.exist.xquery.functions.fn.transform.Transform.SAXON_PROCESSOR.newXsltCompiler();
209208
final SingleRequestErrorListener errorListener = new SingleRequestErrorListener(Transform.ERROR_LISTENER);
210209
xsltCompiler.setErrorListener(errorListener);
@@ -223,7 +222,7 @@ private XsltExecutable compileExecutable(final Options options) throws XPathExce
223222
xsltCompiler.setURIResolver((href, base) -> {
224223
try {
225224
final URI hrefURI = URI.create(href);
226-
if (!options.resolvedStylesheetBaseURI.isPresent() && !hrefURI.isAbsolute() && StringUtils.isEmpty(base)) {
225+
if (options.resolvedStylesheetBaseURI.isEmpty() && !hrefURI.isAbsolute() && StringUtils.isEmpty(base)) {
227226
final XPathException resolutionException = new XPathException(fnTransform,
228227
ErrorCodes.XTSE0165,
229228
"transform using a relative href, \n" +
@@ -266,8 +265,7 @@ private XPathException originalXPathException(final String prefix, @Nonnull fina
266265

267266
cause = e;
268267
while (cause != null) {
269-
if (cause instanceof net.sf.saxon.trans.XPathException) {
270-
final net.sf.saxon.trans.XPathException xPathException = (net.sf.saxon.trans.XPathException)cause;
268+
if (cause instanceof final net.sf.saxon.trans.XPathException xPathException) {
271269
final StructuredQName from = xPathException.getErrorCodeQName();
272270
if (from != null) {
273271
final QName errorCodeQName = new QName(from.getLocalPart(), from.getURI(), from.getPrefix());
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
eXist-db Open Source Native XML Database
5+
Copyright (C) 2001 The eXist-db Authors
6+
7+
8+
http://www.exist-db.org
9+
10+
This library is free software; you can redistribute it and/or
11+
modify it under the terms of the GNU Lesser General Public
12+
License as published by the Free Software Foundation; either
13+
version 2.1 of the License, or (at your option) any later version.
14+
15+
This library is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
Lesser General Public License for more details.
19+
20+
You should have received a copy of the GNU Lesser General Public
21+
License along with this library; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23+
24+
-->
25+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xs math xd tei" version="3.0">
26+
27+
<xsl:param name="heading" as="xs:boolean" select="true()"/>
28+
<xsl:param name="documentID" as="xs:string" select="/tei:TEI/@xml:id"/>
29+
30+
<xsl:output indent="true"/>
31+
32+
<xsl:mode on-no-match="shallow-skip" use-accumulators="#all"/>
33+
<xsl:mode name="html" on-no-match="text-only-copy"/>
34+
35+
<xsl:accumulator name="document-nos" initial-value="()" as="xs:string*">
36+
<xsl:accumulator-rule match="tei:div[@type eq 'document']" select="($value, @n)" phase="end"/>
37+
</xsl:accumulator>
38+
39+
<xsl:accumulator name="document-ids" initial-value="()" as="xs:string*">
40+
<xsl:accumulator-rule match="tei:div[tei:div/@type = 'document']" select="()"/>
41+
<xsl:accumulator-rule match="tei:div[@type eq 'document']" select="($value, @xml:id)" phase="end"/>
42+
</xsl:accumulator>
43+
44+
<xsl:template match="tei:TEI">
45+
<div class="toc">
46+
<div class="toc__header">
47+
<h4 class="title">Contents</h4>
48+
</div>
49+
<nav aria-label="Side navigation,,," class="toc__chapters">
50+
<ul class="chapters js-smoothscroll">
51+
<xsl:apply-templates select="tei:text"/>
52+
</ul>
53+
</nav>
54+
</div>
55+
</xsl:template>
56+
57+
<xsl:template match="tei:div[@xml:id][not(@type = ('document'))]">
58+
<xsl:variable name="accDocs" as="xs:string*" select="accumulator-after('document-nos')"/>
59+
<xsl:variable name="prevDocs" as="xs:string*" select="accumulator-before('document-nos')"/>
60+
<xsl:variable name="docs" as="xs:string*" select="$accDocs[not(. = $prevDocs)]"/>
61+
<xsl:variable name="prevDocIDs" as="xs:string*" select="accumulator-before('document-ids')"/>
62+
<xsl:variable name="docIDs" as="xs:string*" select="accumulator-after('document-ids')[not(. = $prevDocIDs)]"/>
63+
<li data-tei-id="{@xml:id}">
64+
<xsl:if test="exists($docIDs) and tei:div[@type='document']">
65+
<xsl:attribute name="data-tei-documents" select="string-join($docIDs, ' ')"/>
66+
</xsl:if>
67+
68+
<a href="/{$documentID}/{@xml:id}">
69+
<xsl:apply-templates mode="html" select="tei:head"/>
70+
</a>
71+
<xsl:value-of select="(' (Document' || 's'[count($docs) gt 1] || ' ' || $docs[1] || ' - '[count($docs) gt 1] || $docs[last()][count($docs) gt 1] || ')')[exists($docs)]"/>
72+
73+
<xsl:where-populated>
74+
<ul class="chapters__nested">
75+
<xsl:apply-templates/>
76+
</ul>
77+
</xsl:where-populated>
78+
</li>
79+
</xsl:template>
80+
81+
<xsl:template match="tei:div[@xml:id eq 'toc']" priority="2"/>
82+
83+
<xsl:template match="tei:head/tei:note" mode="html"/>
84+
85+
<xsl:template match="tei:lb" mode="html">
86+
<br/>
87+
</xsl:template>
88+
89+
</xsl:stylesheet>
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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+
import module namespace xmldb="http://exist-db.org/xquery/xmldb";
26+
27+
declare namespace test="http://exist-db.org/xquery/xqsuite";
28+
29+
declare variable $testTransform:doc := document {
30+
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="output">
31+
<teiHeader>
32+
<fileDesc>
33+
<titleStmt>
34+
<title/>
35+
</titleStmt>
36+
<publicationStmt>
37+
<p>Test document</p>
38+
</publicationStmt>
39+
<sourceDesc>
40+
<p>born digital</p>
41+
</sourceDesc>
42+
</fileDesc>
43+
</teiHeader>
44+
<text>
45+
<front>
46+
<div xml:id="pressrelease" type="section" subtype="press-release">
47+
<head>Press Release</head>
48+
</div>
49+
</front>
50+
<body>
51+
<div type="compilation" xml:id="comp">
52+
<head>Main Book</head>
53+
<div type="chapter" xml:id="ch1">
54+
<head>Chapter One</head>
55+
<div type="document" n="1" xml:id="d1"/>
56+
<div type="document" n="2" xml:id="d2"/>
57+
<div type="document" n="3" xml:id="d3"/>
58+
<div type="document" n="4" xml:id="d4"/>
59+
<div type="document" n="5" xml:id="d5"/>
60+
<div type="document" n="6" xml:id="d6"/>
61+
<div type="document" n="7" xml:id="d7"/>
62+
</div>
63+
<div type="chapter" xml:id="ch2">
64+
<head>Chapter Two</head>
65+
<div type="document" n="8" xml:id="d8"/>
66+
<div type="document" n="9" xml:id="d9"/>
67+
<div type="document" n="10" xml:id="d10"/>
68+
<div type="document" n="11" xml:id="d11"/>
69+
<div type="document" n="12" xml:id="d12"/>
70+
<div type="document" n="13" xml:id="d13"/>
71+
<div type="document" n="14" xml:id="d14"/>
72+
<div type="document" n="15" xml:id="d15"/>
73+
</div>
74+
<div type="chapter" xml:id="ch3">
75+
<head>Chapter Three</head>
76+
<div type="document" n="16" xml:id="d16"/>
77+
<div type="document" n="17" xml:id="d17"/>
78+
<div type="document" n="18" xml:id="d18"/>
79+
<div type="document" n="19" xml:id="d19"/>
80+
<div type="document" n="20" xml:id="d20"/>
81+
<div type="document" n="21" xml:id="d21"/>
82+
</div>
83+
<div type="chapter" xml:id="ch4">
84+
<head>Chapter Four</head>
85+
<div type="document" n="22" xml:id="d22"/>
86+
<div type="document" n="23" xml:id="d23"/>
87+
<div type="document" n="24" xml:id="d24"/>
88+
<div type="document" n="25" xml:id="d25"/>
89+
<div type="document" n="26" xml:id="d26"/>
90+
<div type="document" n="27" xml:id="d27"/>
91+
<div type="document" n="28" xml:id="d28"/>
92+
</div>
93+
</div>
94+
</body>
95+
</text>
96+
</TEI>
97+
};
98+
99+
declare
100+
%test:assertEquals("<div class=""toc""><div class=""toc__header""><h4 class=""title"">Contents</h4></div><nav aria-label=""Side navigation,,,"" class=""toc__chapters""><ul class=""chapters js-smoothscroll""><li data-tei-id=""pressrelease""><a href=""/output/pressrelease"">Press Release</a></li><li data-tei-id=""comp""><a href=""/output/comp"">Main Book</a> (Documents 1 - 28)<ul class=""chapters__nested""><li data-tei-id=""ch1"" data-tei-documents=""d1 d2 d3 d4 d5 d6 d7""><a href=""/output/ch1"">Chapter One</a> (Documents 1 - 7)</li><li data-tei-id=""ch2"" data-tei-documents=""d8 d9 d10 d11 d12 d13 d14 d15""><a href=""/output/ch2"">Chapter Two</a> (Documents 8 - 15)</li><li data-tei-id=""ch3"" data-tei-documents=""d16 d17 d18 d19 d20 d21""><a href=""/output/ch3"">Chapter Three</a> (Documents 16 - 21)</li><li data-tei-id=""ch4"" data-tei-documents=""d22 d23 d24 d25 d26 d27 d28""><a href=""/output/ch4"">Chapter Four</a> (Documents 22 - 28)</li></ul></li></ul></nav></div>")
101+
function testTransform:issue-4609() {
102+
let $create-collection := xmldb:create-collection("/db", "fn_transform_issue_4609")
103+
let $doc-store := xmldb:store("/db/fn_transform_issue_4609", "input.xml", $testTransform:doc)
104+
105+
(: this works :)
106+
let $result := ( fn:transform(map{
107+
"stylesheet-location": 'resource:/org/exist/xquery/tei-toc.xsl',
108+
"source-node": doc('/db/fn_transform_issue_4609/input.xml')
109+
}))
110+
return $result?output
111+
};

0 commit comments

Comments
 (0)