A função dyn: avaliar extensão tem problemas no Xalan-J 2.7.1?

Estou perplexo com o motivo pelo qual o programa de exemplo a seguir se recusa a aplicar minha folha de estilo corretamente. Parece quedyn:evaluate no Xalan 2.7.1 está se recusando a processar determinadas variáveis XPath.

Executando o seguinte programa comxalan-j no caminho de classe produz os seguintes resultados:

package com.testing2.xslt;

import java.io.*;
import java.util.logging.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class DynEvaluateTransform {

    private static final String XSLT = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
"    xmlns:det=\"org:example:DynEvaluateTransform\"\n" +
"    xmlns:dyn=\"http://exslt.org/dynamic\"\n" +
"    extension-element-prefixes=\"dyn\"\n" +
"    version=\"1.0\">\n" +
"    \n" +
"    <xsl:variable name=\"input-doc\" select=\"document('input.xml', /)\" />\n" +
"    <xsl:variable name=\"selections\" select=\"$input-doc/det:selections\" />\n" +
"    \n" +
"    <xsl:template match=\"/\">\n" +
"        <xsl:choose>\n" +
"            <xsl:when test=\"function-available('dyn:evaluate')\">\n" +
"                <xsl:message>dyn:evaluate available</xsl:message>\n" +
"            </xsl:when>\n" +
"            <xsl:otherwise>\n" +
"                <xsl:message>dyn:evaluate not available</xsl:message>\n" +
"            </xsl:otherwise>\n" +
"        </xsl:choose>\n" +
"        <xsl:message>input.xml content:</xsl:message>\n" +
"        <xsl:for-each select=\"$selections/*\">\n" +
"            <xsl:message>{<xsl:value-of select=\"namespace-uri()\"/>}<xsl:value-of select=\"local-name()\"/></xsl:message>\n" +
"        </xsl:for-each>        \n" +
"        <xsl:for-each select=\"//@condition\">\n" +
"            <xsl:message><xsl:value-of select=\".\"/></xsl:message>\n" +
"            <xsl:message><xsl:value-of select=\"string(dyn:evaluate(string(.)))\"/></xsl:message>\n" +
"        </xsl:for-each>\n" +
"    </xsl:template>\n" +
"    \n" +
"</xsl:stylesheet>";

    private static final String EXAMPLE = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foos xmlns=\"org:example:DynEvaluateTransform\">    \n" +
"    <foo condition=\"true()\" />    \n" +
"    <foo condition=\"false()\" />    \n" +
"    <foo condition=\"false() or true()\" />\n" +
"    <foo condition=\"$selections\" />\n" +
"    <foo condition=\"$selections/*\" />\n" +
"    <foo condition=\"$selections/*[local-name()='a']\" />\n" +
"    <foo condition=\"$selections/element::node()[local-name()='a']\" />\n" +
"    <foo condition=\"local-name($selections/*)\" />\n" +
"    <foo condition=\"not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])\" />\n" +
"    <foo condition=\"$selections/*[local-name()='b' and namespace-uri()='org:example:foo']\" />\n" +
"    <foo condition=\"$selections/*[local-name()='c' and namespace-uri()='org:example:foo']\" />\n" +
"    <foo condition=\"not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])\" />\n" +
"</foos>";

    private static final String INPUT = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<selections xmlns=\"org:example:DynEvaluateTransform\">\n" +
"    <a xmlns=\"org:example:foo\"/>\n" +
"    <b xmlns=\"org:example:foo\"/>\n" +
"    <c xml,ns=\"org:example:foo\"/>\n" +
"</selections>";

    private TransformerFactory xalanTransFact;    

    public DynEvaluateTransform() {
        xalanTransFact = new org.apache.xalan.processor.TransformerFactoryImpl();
        xalanTransFact.setURIResolver(new Resolver());
    }

    private void applyTransform() {
        // XSLT(EXAMPLE) --> output.xml
        //         ^
        //         |
        //       INPUT
        OutputStreamWriter writer = null;

        try {
            String outputFileName = DynEvaluateTransform.getLocalFileName("output.xml");

            File file = new File(outputFileName);
            writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");

            System.out.println(org.apache.xalan.Version.getVersion());

            Transformer transformer = xalanTransFact.newTransformer(new StreamSource(new StringReader(XSLT)));
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");

            transformer.transform(
                    new StreamSource(new StringReader(EXAMPLE)),
                    new StreamResult(writer));

        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException ex) {
                }
            }
        }
    }

    private void rebuildInput() {
        // ignore - this just writes the input.xml file, so we can later reference it
        StringReader strReader = null;
        OutputStreamWriter fileWriter = null;
        try {
            String fileName = getLocalFileName("input.xml");

            strReader = new StringReader(INPUT);
            File file = new File(fileName);
            fileWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");

            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");

            transformer.transform(
                    new StreamSource(strReader),
                    new StreamResult(fileWriter));

        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (strReader != null) {
                strReader.close();
            }
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException ex) {
                }
            }
        }
    }

    public static void main(String[] args) {
        DynEvaluateTransform det = new DynEvaluateTransform();
        det.rebuildInput();
        det.applyTransform();
    }   

    private static String getLocalFileName(String href) {
        String name = System.getProperty("user.dir");
        if (!name.endsWith(File.separator)) {
            name += File.separator;
        }
        name += href;
        return name;
    }

    private static class Resolver implements URIResolver {

        @Override
        public Source resolve(String href, String base) throws TransformerException {
            if ("input.xml".equals(href)) {                
                return new StreamSource(new File(DynEvaluateTransform.getLocalFileName(href)));
            } else {
                return null;
            }
        }
    }
}
Xalan Java 2.7.1
SystemId Unknown; Line #14; Column #30; dyn:evaluate available
SystemId Unknown; Line #20; Column #22; input.xml content:
SystemId Unknown; Line #22; Column #26; {org:example:foo}a
SystemId Unknown; Line #22; Column #26; {org:example:foo}b
SystemId Unknown; Line #22; Column #26; {org:example:foo}c
SystemId Unknown; Line #25; Column #26; true()
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; false()
SystemId Unknown; Line #26; Column #26; false
SystemId Unknown; Line #25; Column #26; false() or true()
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; $selections
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; $selections/*
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='a']
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; $selections/element::node()[local-name()='a']
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; local-name($selections/*)
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='b' and namespace-uri()='org:example:foo']
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='c' and namespace-uri()='org:example:foo']
SystemId Unknown; Line #26; Column #26; 
SystemId Unknown; Line #25; Column #26; not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])
SystemId Unknown; Line #26; Column #26; true

O programa de exemplo transforma uma entrada de exemplo (EXAMPLE) usando a transformação fornecida (XSLT), que utiliza um arquivo de entrada (INPUT,input.xml), aberto viadocument() função, como um "argumento". Este arquivo de entrada contém um conjunto de elementos que são testados com expressões XPath (localizadas em EXAMPLE).

A saída do programa indica que odyn:evaluate função é suportada, queinput.xml é lido corretamente, que expressões XPath simples são avaliadas corretamente, mas assim que uma variável XPath é envolvida, ela é interrompida.

Versões legíveis de todos os documentos envolvidos abaixo.

input.xml

<?xml version="1.0" encoding="UTF-8"?>
<selections xmlns="org:example:DynEvaluateTransform">
    <a xmlns="org:example:foo"/>
    <b xmlns="org:example:foo"/>
    <c xmlns="org:example:foo"/>
</selections>

EXEMPLO

<?xml version="1.0" encoding="UTF-8"?>
<foos xmlns="org:example:DynEvaluateTransform">    
    <foo condition="true()" />    
    <foo condition="false()" />    
    <foo condition="false() or true()" />
    <foo condition="$selections" />
    <foo condition="$selections/*" />
    <foo condition="$selections/*[local-name()='a']" />
    <foo condition="$selections/element::node()[local-name()='a']" />
    <foo condition="local-name($selections/*)" />
    <foo condition="not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])" />
    <foo condition="$selections/*[local-name()='b' and namespace-uri()='org:example:foo']" />
    <foo condition="$selections/*[local-name()='c' and namespace-uri()='org:example:foo']" />
    <foo condition="not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])" />
</foos>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:det="org:example:DynEvaluateTransform"
    xmlns:dyn="http://exslt.org/dynamic"
    extension-element-prefixes="dyn"
    version="1.0">

    <xsl:variable name="input-doc" select="document('input.xml', /)" />
    <xsl:variable name="selections" select="$input-doc/det:selections" />

    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="function-available('dyn:evaluate')">
                <xsl:message>dyn:evaluate available</xsl:message>
            </xsl:when>
            <xsl:otherwise>
                <xsl:message>dyn:evaluate not available</xsl:message>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:message>input.xml content:</xsl:message>
        <xsl:for-each select="$selections/*">
            <xsl:message>{<xsl:value-of select="namespace-uri()"/>}<xsl:value-of select="local-name()"/></xsl:message>
        </xsl:for-each>        
        <xsl:for-each select="//@condition">
            <xsl:message><xsl:value-of select="."/></xsl:message>
            <xsl:message><xsl:value-of select="string(dyn:evaluate(string(.)))"/></xsl:message>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

O Xalan não suporta variáveis XPath em umdyn:evaluate argumento? Estou definindo as expressões corretamente? Tentando executar esta folha de estilo no oXygen com o Xalan selecionado, relatóriosjava.lang.RuntimeException: ElemTemplateElement error: Function not supported! quando uma variável XPath é encontrada pela primeira vez.

Editar:

Reescrevi a pergunta para esclarecer qual é o meu problema real.

questionAnswers(1)

yourAnswerToTheQuestion