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

缺少节点或属性时创建HTML TD单元格,html,xslt-1.0,apply-templates,Html,Xslt 1.0,Apply Templates,我正在改进我继承的一些样式表,并将它们从使用转换为。我将使用的一个XML文件的一个非常简化的版本是: <Root> <Row ID="123" Region="AMS"> <First>Graham</First> <Last>Smith</Last> <Sales>12345.85</Sales> <Team>Tea

我正在改进我继承的一些样式表,并将它们从使用
转换为
。我将使用的一个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>

格雷厄姆
史密斯
12345.85
A队
约翰
棕色的
18765.85
C队
安妮
琼斯
34567.85
B队
我拥有的新样式表是:

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

正文*{字体系列:Arial;字体大小:11pt}
表{边框折叠:折叠}
td{边框底部:1px实心#D8D8D8;填充:7px}
tr.row1{背景:#F9F9F9;}
td.tdHeader{边框底部:2px实心#DDD;字体重量:700}
但是,由于XML中的第二个节点缺少
属性,结果中的单元格对齐错误,现在“区域”列中有“名字”,而“名字”列中有“姓氏”,依此类推。如果行节点上缺少子节点,也会发生这种情况。例如,没有团队元素

在调用apply模板之前,我曾尝试在最后两个模板中测试丢失的节点,但均无效


有什么想法吗?我错过了什么?我才刚刚开始使用apply templates,但我对其他编写样式表的方法很满意。

暂时来说,这对您的输入很有用:

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

将其更改为
,或者最好更改为
,将解决此问题。正如我在评论中所说,尽量少用
*
。对
的引用可以更改为精确匹配。

您真的需要动态构建列吗?我遇到了以下问题:(1)
区域
行[1]
中缺失,但在其余行中存在;(2)
id
vs
id
。(这就是说,您似乎还非常自由地使用了
*
的匹配项……尝试使用
等来简化。)在XSLT中,显式是值得的。如果预先知道元素和属性的名称,请使用它们。如果您试图构建一个XSLT来容纳多个可能的XML结构,那么请解释关于预期输入的已知内容和未知内容。“我正在改进我继承的一些样式表,并将它们从使用
转换为
”。您认为这一定是一种改进吗?
<xsl:template match="/@* | node()">