当缺少节点或属性时创建HTML TD单元格



我正在改进我继承的一些样式表,并将它们从使用<xsl:for-each>转换为<xsl:apply-templates>。我将要使用的XML文件的一个非常简化的版本是:

<Root>
    <Row ID="123" Region="AMS">
        <First>Graham</First>
        <Last>Smith</Last>
        <Sales>12345.85</Sales>
        <Team>Team A</Team>
    </Row>
        <Row id="321">
        <First>John</First>
        <Last>Brown</Last>
        <Sales>18765.85</Sales>
        <Team>Team C</Team>
    </Row>
        <Row id="456" Region="EMEA">
        <First>Anne</First>
        <Last>Jones</Last>
        <Sales>34567.85</Sales>
        <Team>Team B</Team>
    </Row>
</Root>
我的新样式表是:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
    <xsl:output method="html" indent="yes"/>
    <xsl:variable name="RowCount" select="count(/*/*)"/>
    <xsl:template match="/@* | node()">
        <style>
            body * {font-family:Arial;font-size:11pt}
            table {border-collapse:collapse}
            td {border-bottom:1px solid #D8D8D8;padding:7px}
            tr.row1 {background:#F9F9F9;}
            td.tdHeader {border-bottom:2px solid #DDD;font-weight:700}
        </style>
        <table>
            <thead>
                <tr>
                    <xsl:apply-templates select="*[1]/@*" mode="headerAttributes" />
                    <xsl:apply-templates select="*[1]/*" mode="headerFields"/>
                </tr>
            </thead>
            <tbody>
                <xsl:apply-templates select="*"/>
            </tbody>
        </table>
    </xsl:template>
    <xsl:template match="/*/*/@*" mode="headerAttributes">
        <td class="tdHeader">
            <xsl:value-of select="name()" />
        </td>
    </xsl:template>
    <xsl:template match="/*/*/*" mode="headerFields">
        <td class="tdHeader">
            <xsl:value-of select="name()" />
        </td>
    </xsl:template>
    <xsl:template match="/*/*">
        <tr class="row{position() mod 2}">
            <xsl:apply-templates select="@*" mode="attributes"/>
            <xsl:apply-templates select="*" mode="fields"/>
        </tr>
    </xsl:template>
    <xsl:template match="/*/*/@*" mode="attributes">
        <td>
            <xsl:value-of select="." />
        </td>
    </xsl:template>
    <xsl:template match="/*/*/*" mode="fields">
        <td>
            <xsl:value-of select="." />
        </td>
    </xsl:template>
</xsl:stylesheet>

但是,由于XML中的第二个节点缺少<Region>属性,结果上的单元格排列错误,现在在Region列中有名字,在first name列中有姓氏,等等。如果Row节点上缺少子节点,也会发生这种情况。例如,没有team元素

在调用apply-template之前,以及在最后两个模板中,我尝试测试一个缺失的节点,但是没有效果。

任何想法?我遗漏了什么?我只是刚刚开始使用应用模板,但其他编写样式表的方法我很好。

暂时,这适用于您的输入:

<xsl:template match="Row">
    <tr class="row{position() mod 2}">
        <td><xsl:apply-templates select="@ID|@id" mode="attr2"/></td>
        <td><xsl:apply-templates select="@Region" mode="attr2"/></td>
        <xsl:apply-templates select="*" mode="fields"/>
    </tr>
</xsl:template>
<xsl:template match="@ID|@id|@Region" mode="attr2">
    <b><xsl:value-of select="." /></b>
</xsl:template>

——您可以删除mode="attributes"的所有内容。

即使没有id|IDRegion属性,也强制包含<td>..</td>对。

Saxon 8.8报告错误:

从document-node()节点开始的属性轴永远不会选择任何东西

因为你的

<xsl:template match="/@* | node()">

将其更改为<xsl:template match="node()">,或者最好更改为<xsl:template match="Root">将解决此问题。正如我在评论中所说,尽量少使用*。对RootRow的引用可以更改为精确匹配

相关内容

  • 没有找到相关文章

最新更新