Создать 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> атрибут, ячейки в результате выровнены неправильно, имя в столбце "Регион", фамилия в столбце "Имя" и т. д. Это также происходит, если в узле Row отсутствует дочерний узел. например, нет элемента команды

Я пытался проверить наличие отсутствующего узла перед вызовом apply-template и внутри двух последних шаблонов, но безрезультатно.

Есть идеи? Что мне здесь не хватает? Я только начинаю разбираться в этом с использованием apply-templates, но с другими методами написания таблиц стилей я в порядке.

1 ответ

Предварительно, это работает для вашего ввода:

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

Это заставляет включение <td>..</td> пара, даже если нет id|ID или же Region приписывать.

Saxon 8.8 сообщает об ошибке:

Ось атрибута, начинающаяся с узла document-node(), никогда ничего не выберет

из-за вашего

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

Меняя его на <xsl:template match="node()">или, предпочтительно, чтобы <xsl:template match="Root"> это исправлю. Как я уже сказал в своем комментарии, попробуйте использовать * как можно меньше. Ссылки на Root а также Row могут быть изменены на точные совпадения.

Другие вопросы по тегам