psrikantan
psrikantan

Reputation: 13

HashMap iteration in XSLT 2.0

I have an HashMap object as part of my java model and when I convert it into XML, this is the result...

<transaction>
  <claims>
    <remarksMap>
      <entry>
        <string>XX</string>
        <string>Description 1</string>
      </entry>
      <entry>
        <string>YYY</string>
        <string>Description 2</string>
      </entry>
      <entry>
        <string>ZZZZ</string>
        <string>Description 3</string>
      </entry>
    </remarksMap>
  </claims>
</transaction>

I would like to iterate through the Map object in XSLT but haven't had any luck yet. Posting a sample code from the XSL...

<xsl:for-each select="remarksMap/entry">
  <fo:table-row>
    <fo:table-cell padding="3px" text-align="left">
      <fo:block font-size="7pt">
        <xsl:value-of select="string" />
      </fo:block>
    </fo:table-cell>
  </fo:table-row>
</xsl:for-each>

The Output for this comes like this. It's printing out the entrySet() in a new line. XX Description 1 YYY Description 2 ZZZZ Description 3

I would ideally like to print the keys in the first and the values in the second . Appreciate any help on this!

P.S: I'm using XSL v2.0 and Saxon-HE:9.4 as the processor.

Upvotes: 1

Views: 1941

Answers (1)

Daniel Haley
Daniel Haley

Reputation: 52888

What you would need to do is add a second xsl:for-each to loop over each string and create the fo:table-cell's from that.

<xsl:for-each select="remarksMap/entry">
    <fo:table-row>
        <xsl:for-each select="string">
            <fo:table-cell padding="3px" text-align="left">
                <fo:block font-size="7pt">
                    <xsl:value-of select="."/>
                </fo:block>
            </fo:table-cell>                                
        </xsl:for-each>
    </fo:table-row>
</xsl:for-each>

You could also use a push style approach...

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="my-page" page-width="8.5in" page-height="11in">
                    <fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="my-page">
                <fo:flow flow-name="xsl-region-body"> 
                    <xsl:apply-templates/>
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>

    <xsl:template match="entry">
        <fo:table-row>
            <xsl:apply-templates/>
        </fo:table-row>
    </xsl:template>

    <xsl:template match="string">
        <fo:table-cell padding="3px" text-align="left">
            <fo:block font-size="7pt">
                <xsl:value-of select="."/>
            </fo:block>
        </fo:table-cell>        
    </xsl:template>

</xsl:stylesheet>

XSL-FO Output

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="my-page" page-width="8.5in" page-height="11in">
         <fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
      </fo:simple-page-master>
   </fo:layout-master-set>
   <fo:page-sequence master-reference="my-page">
      <fo:flow flow-name="xsl-region-body">
         <fo:table-row>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">XX</fo:block>
            </fo:table-cell>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">Description 1</fo:block>
            </fo:table-cell>
         </fo:table-row>
         <fo:table-row>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">YYY</fo:block>
            </fo:table-cell>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">Description 2</fo:block>
            </fo:table-cell>
         </fo:table-row>
         <fo:table-row>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">ZZZZ</fo:block>
            </fo:table-cell>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">Description 3</fo:block>
            </fo:table-cell>
         </fo:table-row>
      </fo:flow>
   </fo:page-sequence>
</fo:root>

Edit

After reading your question a second time, this:

I would ideally like to print the keys in the first and the values in the second .

almost sounds like you want just two cells with all keys in the first cell and all values in the second. If this is the case, you could do something like...

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*/claims/remarksMap">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="my-page" page-width="8.5in" page-height="11in">
                    <fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="my-page">
                <fo:flow flow-name="xsl-region-body"> 
                    <fo:table-row>
                        <fo:table-cell padding="3px" text-align="left">
                            <fo:block font-size="7pt">
                                <xsl:value-of select="entry/string[1]" separator=", "/>
                            </fo:block>
                        </fo:table-cell>        
                        <fo:table-cell padding="3px" text-align="left">
                            <fo:block font-size="7pt">
                                <xsl:value-of select="entry/string[2]" separator=", "/>
                            </fo:block>
                        </fo:table-cell>        
                    </fo:table-row>
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>

</xsl:stylesheet>

XSL-FO Output

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="my-page" page-width="8.5in" page-height="11in">
         <fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
      </fo:simple-page-master>
   </fo:layout-master-set>
   <fo:page-sequence master-reference="my-page">
      <fo:flow flow-name="xsl-region-body">
         <fo:table-row>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">XX, YYY, ZZZZ</fo:block>
            </fo:table-cell>
            <fo:table-cell padding="3px" text-align="left">
               <fo:block font-size="7pt">Description 1, Description 2, Description 3</fo:block>
            </fo:table-cell>
         </fo:table-row>
      </fo:flow>
   </fo:page-sequence>
</fo:root>

Upvotes: 2

Related Questions