Home > Enterprise >  Can this be simplified with key()?
Can this be simplified with key()?

Time:12-01

The following code work fine but I want to simplify it. In these example I have 11 currency denominations (I have only included four here to simplify the question) and I would like a way to simplify this code in a way I don't have to repeat the line with thousand or hundred or fifty ... or one three times. It seems to me it could be done using <xsl:key but I haven't found the way.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:variable name="test">
        <root>
            <other1>
            </other1>
            <currency g="1">
                <sth1>A</sth1>
                <thousand>1</thousand>
                <hundred>2</hundred>
                <fifty>4</fifty>
                <one>10</one>
                <sth2>C</sth2>
            </currency>
            <currency g="2">
                <sth1>A</sth1>
                <sth2>C</sth2>
            </currency>
            <currency g="3">
                <sth1>A</sth1>
                <thousand>1</thousand>
                <hundred>2</hundred>
                <fifty>4</fifty>
                <one>10</one>
                <sth2>C</sth2>
            </currency>
            <other2>
            </other2>
        </root>
    </xsl:variable>
    <xsl:variable xmlns:xalan="http://xml.apache.org/xalan" name="curr" select="xalan:nodeset($test)/root"/>
    
    
    <xsl:template match="/">
        <root>
            <xsl:call-template name="currency"/>
        </root>
    </xsl:template>
    
    <xsl:template name="currency">
        <xsl:for-each select="$curr/currency[thousand or hundred or fifty or one]">
            <xsl:if test="position() mod 3 = 1">
                <xsl:variable name="nextSibling1" select="following-sibling::currency[thousand or hundred or fifty or one][1]"/>
                <xsl:variable name="nextSibling2" select="following-sibling::currency[thousand or hundred or fifty or one][2]"/>
                <col1>
                    <xsl:apply-templates select="." mode="total"/>
                </col1>
                 <col2>
                     <xsl:apply-templates select="$nextSibling1" mode="total"/>
                 </col2>
                 <col3>
                     <xsl:apply-templates select="$nextSibling2" mode="total"/>
                 </col3>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
    
    <xsl:template match="currency" mode="total">
        <xsl:value-of select="thousand*1000   hundred*100   fifty*50   one"/>
    </xsl:template>
    
    <xsl:template match="*"/>
</xsl:stylesheet>

This is the output:

<root>
<col1>1410</col1>
<col2>1410</col2>
<col3/>
</root>

CodePudding user response:

I am still not sure what exactly your code is supposed to accomplish. If you don't want to repeat the [thousand or hundred or fifty or one] predicate, then maybe try something like

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:variable name="test">
        <root>
            <other1>
            </other1>
            <currency g="1">
                <sth1>A</sth1>
                <thousand>1</thousand>
                <hundred>2</hundred>
                <fifty>4</fifty>
                <one>10</one>
                <sth2>C</sth2>
            </currency>
            <currency g="2">
                <sth1>A</sth1>
                <sth2>C</sth2>
            </currency>
            <currency g="3">
                <sth1>A</sth1>
                <thousand>1</thousand>
                <hundred>2</hundred>
                <fifty>4</fifty>
                <one>10</one>
                <sth2>C</sth2>
            </currency>
            <other2>
            </other2>
        </root>
    </xsl:variable>

    <xsl:variable xmlns:xalan="http://xml.apache.org/xalan" name="curr" select="xalan:nodeset($test)/root/currency[thousand or hundred or fifty or one]"/>
    
    <xsl:template match="/">
        <root>
            <xsl:for-each select="$curr">
                <xsl:variable name="i" select="position()" />
                <xsl:if test="$i mod 3 = 1">
                    <col1 >
                        <xsl:apply-templates select="." mode="total"/>
                    </col1>
                     <col2>
                         <xsl:apply-templates select="$curr[$i   1]" mode="total"/>
                     </col2>
                     <col3>
                         <xsl:apply-templates select="$curr[$i   2]" mode="total"/>
                     </col3>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
    
     <xsl:template match="currency" mode="total">
         <xsl:value-of select="thousand*1000   hundred*100   fifty*50   one"/>
    </xsl:template>
    
</xsl:stylesheet>
  • Related