Skip to content

Commit

Permalink
Merge pull request #4883 from evolvedbinary/hotfix/eb-4609-transform-…
Browse files Browse the repository at this point in the history
…globals

Fix missing fn:transform global parameters
  • Loading branch information
adamretter authored May 10, 2023
2 parents 01336be + 1086615 commit 6314769
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import net.sf.saxon.s9api.XdmValue;
import org.apache.commons.lang3.StringUtils;
import org.exist.dom.memtree.NamespaceNode;
import org.exist.dom.persistent.NodeProxy;
import org.exist.security.PermissionDeniedException;
import org.exist.xquery.ErrorCodes;
import org.exist.xquery.XPathException;
Expand Down Expand Up @@ -530,7 +531,12 @@ private Source resolvePossibleStylesheetLocation(final String location) throws X
"Can not access '" + location + "'" + e.getMessage());
}
if (document != null && document.hasOne() && Type.subTypeOf(document.getItemType(), Type.NODE)) {
return new DOMSource((Node) document.itemAt(0));
if (document instanceof NodeProxy proxy) {
return new DOMSource(proxy.getNode());
}
else if (document.itemAt(0) instanceof Node node) {
return new DOMSource(node);
}
}
throw new XPathException(fnTransform, ErrorCodes.FODC0002,
"Location '"+ location + "' returns an item which is not a document node");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.dom.QName;
import org.exist.dom.memtree.DocumentImpl;
import org.exist.util.Holder;
import org.exist.xquery.ErrorCodes;
import org.exist.xquery.XPathException;
Expand Down Expand Up @@ -173,7 +172,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
final Document document;
Source source = sourceNode.get();
final Node node = ((DOMSource)sourceNode.get()).getNode();
if (!(node instanceof DocumentImpl)) {
if (!(node instanceof org.exist.dom.memtree.DocumentImpl) && !(node instanceof org.exist.dom.persistent.DocumentImpl)) {
//The source may not be a document
//If it isn't, it should be part of a document, so we build a DOMSource to use
document = node.getOwnerDocument();
Expand All @@ -190,7 +189,6 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
final Transform.TemplateInvocation invocation = new Transform.TemplateInvocation(
options, sourceNode, delivery, xslt30Transformer, resultDocuments);
return invocation.invoke();

} catch (final SaxonApiException | UncheckedXPathException e) {
throw originalXPathException("Could not transform input: ", e, ErrorCodes.FOXT0003);
}
Expand Down Expand Up @@ -220,7 +218,7 @@ private XsltExecutable compileExecutable(final Options options) throws XPathExce
xsltCompiler.setURIResolver((href, base) -> {
try {
final URI hrefURI = URI.create(href);
if (!options.resolvedStylesheetBaseURI.isPresent() && !hrefURI.isAbsolute() && StringUtils.isEmpty(base)) {
if (options.resolvedStylesheetBaseURI.isEmpty() && !hrefURI.isAbsolute() && StringUtils.isEmpty(base)) {
final XPathException resolutionException = new XPathException(fnTransform,
ErrorCodes.XTSE0165,
"transform using a relative href, \n" +
Expand Down Expand Up @@ -263,8 +261,7 @@ private XPathException originalXPathException(final String prefix, @Nonnull fina

cause = e;
while (cause != null) {
if (cause instanceof net.sf.saxon.trans.XPathException) {
final net.sf.saxon.trans.XPathException xPathException = (net.sf.saxon.trans.XPathException)cause;
if (cause instanceof final net.sf.saxon.trans.XPathException xPathException) {
final StructuredQName from = xPathException.getErrorCodeQName();
if (from != null) {
final QName errorCodeQName = new QName(from.getLocalPart(), from.getURI(), from.getPrefix());
Expand Down
89 changes: 89 additions & 0 deletions exist-core/src/test/resources/org/exist/xquery/tei-toc.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
eXist-db Open Source Native XML Database
Copyright (C) 2001 The eXist-db Authors
info@exist-db.org
http://www.exist-db.org
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-->
<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">

<xsl:param name="heading" as="xs:boolean" select="true()"/>
<xsl:param name="documentID" as="xs:string" select="/tei:TEI/@xml:id"/>

<xsl:output indent="true"/>

<xsl:mode on-no-match="shallow-skip" use-accumulators="#all"/>
<xsl:mode name="html" on-no-match="text-only-copy"/>

<xsl:accumulator name="document-nos" initial-value="()" as="xs:string*">
<xsl:accumulator-rule match="tei:div[@type eq 'document']" select="($value, @n)" phase="end"/>
</xsl:accumulator>

<xsl:accumulator name="document-ids" initial-value="()" as="xs:string*">
<xsl:accumulator-rule match="tei:div[tei:div/@type = 'document']" select="()"/>
<xsl:accumulator-rule match="tei:div[@type eq 'document']" select="($value, @xml:id)" phase="end"/>
</xsl:accumulator>

<xsl:template match="tei:TEI">
<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">
<xsl:apply-templates select="tei:text"/>
</ul>
</nav>
</div>
</xsl:template>

<xsl:template match="tei:div[@xml:id][not(@type = ('document'))]">
<xsl:variable name="accDocs" as="xs:string*" select="accumulator-after('document-nos')"/>
<xsl:variable name="prevDocs" as="xs:string*" select="accumulator-before('document-nos')"/>
<xsl:variable name="docs" as="xs:string*" select="$accDocs[not(. = $prevDocs)]"/>
<xsl:variable name="prevDocIDs" as="xs:string*" select="accumulator-before('document-ids')"/>
<xsl:variable name="docIDs" as="xs:string*" select="accumulator-after('document-ids')[not(. = $prevDocIDs)]"/>
<li data-tei-id="{@xml:id}">
<xsl:if test="exists($docIDs) and tei:div[@type='document']">
<xsl:attribute name="data-tei-documents" select="string-join($docIDs, ' ')"/>
</xsl:if>

<a href="/{$documentID}/{@xml:id}">
<xsl:apply-templates mode="html" select="tei:head"/>
</a>
<xsl:value-of select="(' (Document' || 's'[count($docs) gt 1] || ' ' || $docs[1] || ' - '[count($docs) gt 1] || $docs[last()][count($docs) gt 1] || ')')[exists($docs)]"/>

<xsl:where-populated>
<ul class="chapters__nested">
<xsl:apply-templates/>
</ul>
</xsl:where-populated>
</li>
</xsl:template>

<xsl:template match="tei:div[@xml:id eq 'toc']" priority="2"/>

<xsl:template match="tei:head/tei:note" mode="html"/>

<xsl:template match="tei:lb" mode="html">
<br/>
</xsl:template>

</xsl:stylesheet>
111 changes: 111 additions & 0 deletions exist-core/src/test/xquery/xquery3/transform/fnTransformIssue4609.xqm
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
(:
: eXist-db Open Source Native XML Database
: Copyright (C) 2001 The eXist-db Authors
:
: info@exist-db.org
: http://www.exist-db.org
:
: This library is free software; you can redistribute it and/or
: modify it under the terms of the GNU Lesser General Public
: License as published by the Free Software Foundation; either
: version 2.1 of the License, or (at your option) any later version.
:
: This library is distributed in the hope that it will be useful,
: but WITHOUT ANY WARRANTY; without even the implied warranty of
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
: Lesser General Public License for more details.
:
: You should have received a copy of the GNU Lesser General Public
: License along with this library; if not, write to the Free Software
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
:)
xquery version "3.1";

module namespace testTransform="http://exist-db.org/xquery/test/function_transform";
import module namespace xmldb="http://exist-db.org/xquery/xmldb";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare variable $testTransform:doc := document {
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="output">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
</titleStmt>
<publicationStmt>
<p>Test document</p>
</publicationStmt>
<sourceDesc>
<p>born digital</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<front>
<div xml:id="pressrelease" type="section" subtype="press-release">
<head>Press Release</head>
</div>
</front>
<body>
<div type="compilation" xml:id="comp">
<head>Main Book</head>
<div type="chapter" xml:id="ch1">
<head>Chapter One</head>
<div type="document" n="1" xml:id="d1"/>
<div type="document" n="2" xml:id="d2"/>
<div type="document" n="3" xml:id="d3"/>
<div type="document" n="4" xml:id="d4"/>
<div type="document" n="5" xml:id="d5"/>
<div type="document" n="6" xml:id="d6"/>
<div type="document" n="7" xml:id="d7"/>
</div>
<div type="chapter" xml:id="ch2">
<head>Chapter Two</head>
<div type="document" n="8" xml:id="d8"/>
<div type="document" n="9" xml:id="d9"/>
<div type="document" n="10" xml:id="d10"/>
<div type="document" n="11" xml:id="d11"/>
<div type="document" n="12" xml:id="d12"/>
<div type="document" n="13" xml:id="d13"/>
<div type="document" n="14" xml:id="d14"/>
<div type="document" n="15" xml:id="d15"/>
</div>
<div type="chapter" xml:id="ch3">
<head>Chapter Three</head>
<div type="document" n="16" xml:id="d16"/>
<div type="document" n="17" xml:id="d17"/>
<div type="document" n="18" xml:id="d18"/>
<div type="document" n="19" xml:id="d19"/>
<div type="document" n="20" xml:id="d20"/>
<div type="document" n="21" xml:id="d21"/>
</div>
<div type="chapter" xml:id="ch4">
<head>Chapter Four</head>
<div type="document" n="22" xml:id="d22"/>
<div type="document" n="23" xml:id="d23"/>
<div type="document" n="24" xml:id="d24"/>
<div type="document" n="25" xml:id="d25"/>
<div type="document" n="26" xml:id="d26"/>
<div type="document" n="27" xml:id="d27"/>
<div type="document" n="28" xml:id="d28"/>
</div>
</div>
</body>
</text>
</TEI>
};

declare
%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>")
function testTransform:issue-4609() {
let $create-collection := xmldb:create-collection("/db", "fn_transform_issue_4609")
let $doc-store := xmldb:store("/db/fn_transform_issue_4609", "input.xml", $testTransform:doc)

(: this works :)
let $result := ( fn:transform(map{
"stylesheet-location": 'resource:/org/exist/xquery/tei-toc.xsl',
"source-node": doc('/db/fn_transform_issue_4609/input.xml')
}))
return $result?output
};

0 comments on commit 6314769

Please sign in to comment.