Skip to content

[bugfix] fn:transform: Conversion and treeIndex problems#5882

Merged
line-o merged 2 commits into
eXist-db:develop-6.x.xfrom
nverwer:develop-6.x.x
Feb 17, 2026
Merged

[bugfix] fn:transform: Conversion and treeIndex problems#5882
line-o merged 2 commits into
eXist-db:develop-6.x.xfrom
nverwer:develop-6.x.x

Conversation

@nverwer

@nverwer nverwer commented Sep 23, 2025

Copy link
Copy Markdown

Description

This is a retry for #5680 which was botched after I changed my develop-6.x.x branch.

The fn:transform function sometimes produced NullPointerExceptions. This happened for documents containing nodes of type org.exist.dom.memtree.ElementImpl and other subtypes of org.exist.dom.memtree.NodeImpl.

The function org.exist.xquery.functions.fn.transform.Convert.ToSaxon.ofNode(Node) uses org.exist.xquery.functions.fn.transform.TreeUtils.treeIndex(Node) to get a 'path' (as a list of indexes) of the Node in its containing document. This 'path' is used to find the node in a newly built document that is suitable for use by Saxon.
Using the 'path' that the treeIndex function produces assumes that it starts at the document node.

However, some nodes do not have a containing document. Specifically, in org.exist.dom.memtree.NodeImpl.getParentNode():

if (parent.getNodeType() == DOCUMENT_NODE && !((DocumentImpl) parent).isExplicitlyCreated()) {
            /*
                All nodes in the MemTree will return an Owner document due to how the MemTree is implemented,
                however the explicitlyCreated flag tells us whether there "really" was a Document Node or not.
                See https://github.com/eXist-db/exist/issues/1463
             */
            return null;

In this case, the 'path' returned by treeIndex does not contain the index (0) for the root node, and org.exist.xquery.functions.fn.transform.TreeUtils.xdmNodeAtIndex(XdmNode, List<Integer>) will return null when a node is expected.

The proposed fix tests for this case. Going up the ancestor chain, when a node that is not a document node and that does not have a parent is found, the index 0 for this root element is inserted in the 'path'.

The PR also adds support for using maps and arrays as parameters in a XSLT transformation.

Testing

The NullPointerException happened in a rather complicated XQuery with documents composed from several sources.
I have not yet been able to make a simple test case.

@dizzzz

dizzzz commented Oct 4, 2025

Copy link
Copy Markdown
Member

I recognize that under some conditions there is not a "DocumentNode"; I need to recall the context, it is some time ago.

@dizzzz dizzzz requested review from a team and wolfgangmm October 4, 2025 16:10

@reinhapa reinhapa left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small note...

@duncdrum duncdrum added needs develop port needs XQSuite test XQSuite test required to reproduce labels Oct 6, 2025
@duncdrum duncdrum moved this to In progress in v6.4.1 release Feb 17, 2026
Also adds support for using maps and arrays as parameters in a XSLT transformation.
@duncdrum duncdrum force-pushed the develop-6.x.x branch 2 times, most recently from 0e23845 to c6e4557 Compare February 17, 2026 12:07
@duncdrum duncdrum marked this pull request as draft February 17, 2026 12:08
@duncdrum

Copy link
Copy Markdown
Contributor

results against 6.4.0

<testsuites>
    <testsuite package="http://exist-db.org/xquery/test/function_transform" timestamp="2026-02-17T12:55:05.283Z" tests="3" failures="0" errors="3" pending="0" time="PT0.006S">
        <testcase name="memtree-second-child" class="testTransform:memtree-second-child">
            <error type="java:java.lang.NullPointerException" message=""/>
        </testcase>
        <testcase name="stored-doc-with-attributes" class="testTransform:stored-doc-with-attributes">
            <error type="java:java.lang.ClassCastException" message="class org.exist.dom.persistent.NodeProxy cannot be cast to class org.w3c.dom.Node (org.exist.dom.persistent.NodeProxy is in unnamed module of loader 'app'; org.w3c.dom.Node is in module java.xml of loader 'bootstrap')"/>
        </testcase>
        <testcase name="stylesheet-params-map-array" class="testTransform:stylesheet-params-map-array">
            <error type="err:XPTY0004" message="It is a type error if, during the static analysis phase, an expression is found to have a static type that is not appropriate for the context in which the expression occurs, or during the dynamic evaluation phase, the dynamic type of a value does not match a required type as specified by the matching rules in 2.5.4 SequenceType Matching. Item [ x, y, z ] of type array(*) could not be converted to an eXist XdmValue"/>
        </testcase>
    </testsuite>
</testsuites>

if ci is green this is ready from my view

@duncdrum duncdrum marked this pull request as ready for review February 17, 2026 13:17

@line-o line-o left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to you both @nverwer and @duncdrum 🎉

@duncdrum duncdrum moved this from In progress to In review in v6.4.1 release Feb 17, 2026
@duncdrum

Copy link
Copy Markdown
Contributor

see #6055

@nverwer many thanks for the fix. I added tests and created a forward port. During rebasing the commit author seems to be wrongly displayed here on GitHub. Many apologies, but I have no clue, it seems to be a display issues only. The commit log names you as the author of the fix.

@line-o line-o merged commit bf2cc68 into eXist-db:develop-6.x.x Feb 17, 2026
12 of 13 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in v6.4.1 release Feb 17, 2026
line-o added a commit that referenced this pull request Feb 23, 2026
Port of #5882: "[bugfix] fn:transform: Conversion and treeIndex problems"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants