XSLT将XML表转换为HTML表,并在saxon8.jar中使用align char属性获取错误

时间:2016-03-31 06:05:39

标签: xml xslt

请建议,如何解决XSLT使用 saxon8.jar 运行时出现的错误,但是相同的XSLT和输入正在提供 saxon9he.jar 的正确结果如下图所示。

在XSLT 91中,97和104行有一些错误,如下面的错误图像所示。请建议,如何解决这些错误。鉴于XSLT脚本有点大,但在此处发布以显示完整的结果。

XML:

<article>
<table id="t1"><label>Table 1</label><caption>Table caption</caption><tgroup cols="4"><colspec colnum="1" colname="col1"/><colspec colnum="2" colname="col2"/><colspec colnum="3" colname="col3"/><colspec colnum="4" colname="col4"/>
<thead>
<row><entry>No</entry><entry namest="col2" nameend="col4">Cells</entry></row>
<row rowsep="1"><entry></entry><entry>106</entry><entry>406</entry><entry>107</entry></row></thead>

<tbody>
<row><entry>1</entry><entry align="char" char="." namest="col2" nameend="col3">821.23</entry><entry align="char" char=".">1115.6</entry></row>
<row><entry>2</entry><entry align="char" char=".">13.1</entry><entry align="char" char=".">1.3</entry><entry align="char" char=".">9</entry></row>
<row><entry>3</entry><entry align="char" char=".">14.5</entry><entry align="char" char=".">2120.9</entry><entry align="char" char=".">7.8</entry></row>
<row><entry>4</entry><entry align="char" char=".">18.9</entry><entry align="char" char=".">20.4</entry><entry align="char" char=".">22.356</entry></row>
</tbody></tgroup></table>
</article>

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink" 
xmlns:mml="http://www.w3.org/1998/Math/MathML" 
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="html"/>

<xsl:template match="table"><!--Table -->
    <div>
        <xsl:attribute name="id">
            <xsl:choose>
                <xsl:when test="number(tgroup/@cols) gt 4"><xsl:text>table-dc</xsl:text></xsl:when>
                <xsl:otherwise><xsl:text>table-sc</xsl:text></xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <Table border="1">
            <xsl:attribute name="class">
                <xsl:choose>
                    <xsl:when test="@frame"><xsl:value-of select="concat('table-', @frame)"/></xsl:when>
                    <xsl:otherwise>table</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <a><xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute></a>
        <xsl:apply-templates select="caption"/>
        <xsl:apply-templates select="source"/>
        <xsl:apply-templates select="tgroup"/>
        </Table>
    </div>
</xsl:template>

<xsl:template match="thead|tbody"><xsl:apply-templates/></xsl:template>

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

<xsl:template match="entry"><!--Table cells -->
    <xsl:variable name="var1"><xsl:value-of select="number(substring-after(@namest, 'col'))"/></xsl:variable>
    <xsl:variable name="var2"><xsl:value-of select="number(substring-after(@nameend, 'col'))"/></xsl:variable>
    <xsl:variable name="varColSpan">
        <xsl:value-of select="(number($var2)-number($var1))+1"/>
    </xsl:variable>
    <xsl:if test="ancestor::thead">
        <th>
            <xsl:if test="@morerows"><xsl:attribute name="rowspan"><xsl:value-of select="@morerows+1"/></xsl:attribute></xsl:if><!--RowSpan-->
            <xsl:if test="@namest"><!--Col span-->
                <xsl:attribute name="colspan"><xsl:value-of select="$varColSpan"/></xsl:attribute>
            </xsl:if>
            <xsl:if test="@align"><xsl:attribute name="style" select="concat('text-align:', @align)"/></xsl:if>
            <xsl:if test="number(@rowsep) gt 0">
                <xsl:attribute name="class">
                    <xsl:choose>
                        <xsl:when test="number(@rowsep) gt 0">rowsep</xsl:when>
                    </xsl:choose>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates/>
        </th>
    </xsl:if>
    <xsl:if test="ancestor::tbody">
        <td>
            <xsl:if test="@morerows"><xsl:attribute name="rowspan"><xsl:value-of select="@morerows+1"/></xsl:attribute></xsl:if><!--RowSpan-->
            <xsl:if test="@namest"><!--Col span-->
                <xsl:attribute name="colspan"><xsl:value-of select="$varColSpan"/></xsl:attribute>
            </xsl:if>
            <xsl:if test="@align"><xsl:attribute name="style" select="concat('text-align:', @align)"/></xsl:if>

            <xsl:if test="@align='char' and  @char and not(ancestor::table//tbody//entry/@morerows)">
                <xsl:call-template name="tempAlignCHAR">
                    <xsl:with-param name="paramLen" select="if(contains(., @char)) then string-length(substring-before(., @char)) else string-length(.)"/>
                    <xsl:with-param name="paramPos" select="position()"/>
                    <xsl:with-param name="paramChar" select="@char"/>
                </xsl:call-template>
            </xsl:if>
            <xsl:apply-templates/>
        </td>
    </xsl:if>
</xsl:template>

    <xsl:template name="tempAlignCHAR">
        <xsl:param name="paramLen"/>
        <xsl:param name="paramPos"/>
        <xsl:param name="paramChar"/>

        <xsl:variable name="varPresentPosition">
            <xsl:value-of select="number($paramPos) 
                + 
                sum(preceding-sibling::entry/@nameend/number(substring-after(., 'col')))
                 - 
                sum(preceding-sibling::entry/@namest/number(substring-after(., 'col')))"/><!--Error1-->
        </xsl:variable>

        <xsl:variable name="var1">
            <xsl:for-each select="ancestor::tbody/row/entry[number(position()) 
                + sum(preceding-sibling::entry/@nameend/number(substring-after(., 'col'))) 
                - sum(preceding-sibling::entry/@namest/number(substring-after(., 'col'))) = 
                $varPresentPosition][@align='char' and @char]/string-length(substring-before(., $paramChar))"><!--Error2-->
                <xsl:sort select="." order="descending"/>
                    <xsl:if test="position()=1"><xsl:value-of select="number(.)"/></xsl:if>
            </xsl:for-each>
        </xsl:variable>

        <xsl:variable name="var2"><xsl:value-of select="number($paramLen)"/></xsl:variable>
        <xsl:variable name="var3"><xsl:value-of select="number($var1)-number($var2)"/></xsl:variable>

        <font style="color:white">
            <xsl:for-each select="1 to $var3">
                <xsl:value-of select="'0'"/>
            </xsl:for-each>
        </font>

    </xsl:template>
</xsl:stylesheet>

带有saxon9he.jar的HTML表格:

enter image description here

使用saxon8.jar的相同脚本的错误消息: 运行语法:java -jar saxon8.jar CharAlign.xml CharAlign.xsl&gt; CharAlign.html enter image description here

2 个答案:

答案 0 :(得分:1)

我怀疑旧版Saxon 8不支持使用例如foo/function-call(.)并且您必须将其重写为for $f in foo return function-call($f),因此请尝试重写

ancestor::tbody/row/entry[number(position()) 
                + sum(preceding-sibling::entry/@nameend/number(substring-after(., 'col'))) 
                - sum(preceding-sibling::entry/@namest/number(substring-after(., 'col'))) = 
                $varPresentPosition][@align='char' and @char]/string-length(substring-before(., $paramChar))

as

for $e in ancestor::tbody/row/entry[number(position()) 
                + sum(preceding-sibling::entry/@nameend/number(substring-after(., 'col'))) 
                - sum(preceding-sibling::entry/@namest/number(substring-after(., 'col'))) = 
                $varPresentPosition][@align='char' and @char] return string-length(substring-before($e, $paramChar))

答案 1 :(得分:0)

说明“/”的RH操作数必须是节点的错误消息表明您使用的Saxon版本在规范更改之前实现了XSLT 2.0的早期工作草案:它可能至少已有10年历史。 “saxon8.jar”实际上可以是从Saxon 8.0到Saxon 8.9的任何版本,涵盖了广泛的功能变化。没有理由再使用这样一个旧版本了。