Search code examples
xmlxsltxslt-2.0

Need to create the empty entry depends on the column


I'm having the three columns of table input xml, So the tgroup would be <tgroup cols="3" colsep="0" rowsep="0">

<row>
   <entry colname="col1" colsep="0" rowsep="0">Duty</entry>
   <entry colname="col2" colsep="0" rowsep="0"></entry>
   <entry colname="col3" colsep="0" rowsep="0">Correct</entry>
</row>
<row>
   <entry colname="col1" colsep="0" rowsep="0">Dollar</entry>
</row>

XSL I have tried is:

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

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

Output I got is:

<row>
   <entry>Duty</entry>
   <entry></entry>
   <entry>Correct</entry>
</row>
<row>
   <entry>Dollar</entry>
</row>

Excepted Output:

<row>
   <entry>Duty</entry>
   <entry></entry>
   <entry>Correct</entry>
</row>
<row>
   <entry>Dollar</entry>
   <entry></entry>
   <entry></entry>
</row>

Because of that I'm getting validation error and it's depending the tgroup column number. So I want to create the empty entry in the output depend on tgroup column number.


Solution

  • Even you can use the tgroup/@cols value in variable and try to use for generaring the entries like below:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    
        <xsl:output indent="yes"/>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="row">
            <row>
                <xsl:variable name="colno" select="../tgroup/@cols"/>
                <xsl:choose>
                    <xsl:when test="count(entry) = $colno">
                        <xsl:apply-templates/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates/>
                        <xsl:for-each select="count(entry) + 1 to $colno">
                            <entry colname="{concat('col',.)}" colsep="0" rowsep="0"/>
                        </xsl:for-each>
                    </xsl:otherwise>
                </xsl:choose>
            </row>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Follow this link: https://xsltfiddle.liberty-development.net/6rewNxG

    OR

    If you want namest and nameend like spaning then you go with:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    
        <xsl:output indent="yes"/>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
            <xsl:template match="row">
            <row>
                <xsl:variable name="colno" select="../tgroup/@cols"/>
                <xsl:variable name="entrycount" select="count(entry)"/>
                <xsl:for-each select="entry">
                    <entry>
                        <xsl:apply-templates select="@*"/>
                        <xsl:if test="position() = last() and $colno != $entrycount">
                            <xsl:attribute name="namest" select="concat('col',position())"/>
                            <xsl:attribute name="nameend" select="concat('col',$colno)"/>
                        </xsl:if>
                        <xsl:apply-templates/>
                    </entry>
                </xsl:for-each>
            </row>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Follow Link: https://xsltfiddle.liberty-development.net/6rewNxG/1