0

I'm rewriting some XSLT 2.0 templates to make them XSLT 1.0 compatible (Xalan processor). We are using iterations through collections got from java call. But if I try to iterate these collections using for-each and Xalan I am getting

Can not convert #UNKNOWN (java.util.LinkedHashMap) to NodeList!

Is there any way how to do this or is this XSLT 2.0 only? In other words: do I need to convert all collections to NodeSets on my own? Seems that nodeset extension is not the case because it converts the collection to one item nodeset containing all items of original collection.

EDIT:

Formerly we're using Saxon, please see template fragment

<xsl:variable name="profilesTable" select="javaEagle:getAllProfileInfo()"/>
        <xsl:variable name="profilesList" select="javaEagle:getProfileList()"/>
        <xsl:variable name="loopInc" select="0"/>
        <xsl:variable name="profileSize" select="set:size($profilesList)"/>
        <xsl:if test="map:size($profilesTable) > 0">
            <table>
                <tgroup cols="{$profileSize}">
                    <colspec colnum="propertyName" colname="propertyName" colwidth="1*"/>
                    <xsl:for-each select="$profilesList">
                        <xsl:variable name="loopInc" select="$loopInc + 1" />
                        <colspec colnum="{$loopInc}" colname="col{$loopInc}" colwidth="1*"/>
                    </xsl:for-each>
                    <thead>
                        <row>
                        <entry valign="top">Module Property Name</entry>
                            <xsl:for-each select="$profilesList">
                                <entry valign="top"><xsl:value-of select="."/></entry>
                            </xsl:for-each>
                        </row>
                    </thead>
                    <tbody>
                        <xsl:for-each select="common:node-set(map:keySet($profilesTable))">
                            <xsl:variable name="key" select="."/>
                            <row>
                                <entry id="{$key}" namest="col1" nameend="col{$profileSize}" align="left"><b><xsl:value-of select="$key"/></b></entry>
                                    <xsl:variable name="properties" select="map:get($profilesTable, string($key))"/>

Problematic part of code is this:

<xsl:for-each select="common:node-set(map:keySet($profilesTable))">
<xsl:variable name="key" select="."/>
... do somenthing with keys

$profilesTable is HashMap returned from java call.

Without common:nodeset extension I am getting error

   Can not convert #UNKNOWN (java.util.LinkedHashMap) to NodeList!

With common:nodeset it seems loop goes over the whole nodeset as one item.

So the question is how to iterate through keys of returned hashmap using xalan processor.

EDIT2:

Reduced example:

<xsl:template match='/'>    
        <xsl:variable name="profilesTable" select="CustomFunctionsEagle:getAllProfileInfo()"/>
        <xsl:if test="map:size($profilesTable) > 0">
            <table>
                <tbody>
                    <xsl:variable name="keys" select="common:node-set(map:keySet($profilesTable))"/>
                    <AllKeys><xsl:value-of select="$keys"/></AllKeys>
                    <xsl:for-each select="$keys/*">
                        <xsl:for-each select="/"> 
                            <GlobalVariable><xsl:value-of select="."/></GlobalVariable>     
                        </xsl:for-each>
                    </xsl:for-each>
                </tbody>
            </table>
        </xsl:if>
    </xsl:template>

Output:

<?xml version="1.0" encoding="utf-8"?>
<table>
    <tbody>
        <AllKeys>[/AccountState/BW.HOST.NAME, .... another keys]</AllKeys>
    </tbody>
</table>

Expected:

<table>
    <tbody>
        <AllKeys>[/AccountState/BW.HOST.NAME, .... another keys]</AllKeys>
        <GlobalVariable>/AccountState/BW.HOST.NAME</GlobalVariable>
        <GlobalVariable>... another keys</GlobalVariable>
    </tbody>
</table>
  • Somebody downvoted your question (probably) because you don't provide any code examples. Please read https://stackoverflow.com/help/mcve and improve your question, this will greatly increase the chance to get an answer. – laughedelic Mar 20 '18 at 19:03
  • "is this XSLT 2.0 only?" is probably not the most relevant question, as the XSLT 2.0 spec certainly does not in any say how to represent Java collection to XPath or XSLT at all. So it depends on the specific XSLT processor you use and how it interacts with Java. On the other hand representing Java collections of anything but XML nodes is certainly much easier in XSLT/XPath 2.0 with sequences than in XSLT/XPath 1.0 with only node-sets, result tree fragments and primitive types. – Martin Honnen Mar 20 '18 at 21:47
  • Martin, I just found this thread with your answer, maybe this is right direction https://stackoverflow.com/questions/18076417/xslkey-not-working-when-looping-through-nodeset-obtained-with-xalannodeset – Jiri Janecek Mar 21 '18 at 10:08
  • But this example iterates through elements with known structure. – Jiri Janecek Mar 21 '18 at 10:59
  • 1
    The problem you have linked to is simply the use of a result tree fragment converted into a node-set using the node-set extension function and then working with XSLT keys. I don't see that it relates in any way to exposing Java collections to XSLT/XPath. These days with XSLT 3 being the standardized latest version of XSLT and with Saxon 9.8 in the HE version supporting that it seems moving back to XSLT 1.0 and Xalan is an odd move. Granted, Saxon HE only allows calling into Java if you write your extension functions following a certain interface definition but it seems a better supported way. – Martin Honnen Mar 21 '18 at 13:13
  • Ok, Martin, thanks for reply, please can you confirm that assumed construction above (iterating through keyset returned from java call) is not valid for Xalan? Am I right if I say that for all complex structures returned from java we potentially would like to iterate through we need to write recursive conversion to 'DOM structure fragment'? – Jiri Janecek Mar 21 '18 at 16:15
  • I am afraid I don't have the expertise on Xalan to make a definitive statement, it is not clear anyway whether it is the Xalan compiler or interpreter people are using, nor whether it is the standalone Xalan from Apache or the version integrated by Sun/Oracle into the JRE (where I think at some stage they eliminated the interpreter version). http://xalan.apache.org/xalan-j/extensions.html#ext-functions doesn't seem to suggest that there is any particular treatment for Java collections to allow consumption in XSLT. – Martin Honnen Mar 21 '18 at 17:06
  • All right, Martin, thank you, maybe there is somebody who is able to make definitive statement. But at this moment I suspect there is no functionality for handling collections returned from java in standalone xalan. – Jiri Janecek Mar 21 '18 at 18:45

0 Answers0