1

我正在努力改进我继承的一些样式表,并将它们从 using 转换<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 列中,Last name 在 First name 列中等等。如果 Row 节点上缺少子节点,也会发生这种情况。例如,没有团队元素

我曾尝试在调用应用模板之前以及在最后两个模板中测试丢失的节点,但无济于事。

有任何想法吗?我在这里想念什么?我才刚刚开始使用应用模板,但其他编写样式表的方法我都很好。

4

1 回答 1

0

Provisionally, this works for your input:

<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>

-- and you may remove the catch-all for mode="attributes".

This forces the inclusion of a <td>..</td> pair even if there is no id|ID or Region attribute.

Saxon 8.8 reports an error:

The attribute axis starting at a document-node() node will never select anything

because of your

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

Changing it to <xsl:template match="node()">, or, preferably, to <xsl:template match="Root"> will fix this. As I said in my comment, try to use * as little as possible. References to Root and Row can be changed to exact matches.

于 2014-05-18T12:36:50.030 回答