Почему этот шаблон XSL рендерит / генерирует 2 раза? - PullRequest
0 голосов
/ 26 апреля 2018

Сегодня я начал свое первое приключение с xsl в надежде быстро выполнить этот "простой" скрипт. Теперь, спустя 4 часа, я до сих пор не знаю, почему он генерируется 2 раза ...

Мне нужна ваша помощь в поиске ошибки в моем скрипте, потому что я сам не могу ее найти ...

Я создаю HTML-форму на основе XML с помощью XSL.
У меня в основном есть один шаблон, который создается автоматически два раза. И я хочу только один в <div class="columnDiv">.

Снимок экрана с Результат ошибки .
Скриншоты с тем, что я хочу достичь .

Мой XML

<?xml version="1.0" encoding="UTF-8"?>
<labels>
    <options>
        <option type="Top Text 1"/>
        <option type="Top Text 2"/>
        <option type="Top Text 2"/>
    </options>
    <statuses>
        <status type="Correct">
            <answer description="Yes"/>
            <answer description="No"/>
        </status>
        <status type="Error - Type 1">
            <answer description="Option 1"/>
            <answer description="Option 2"/>
            <answer description="Option 3"/>
            <answer description="Option 4"/>
        </status>
        <status type="Error - Type 2">
            <answer description="Option 1"/>
            <answer description="Option 2"/>
            <answer description="Option 3"/>
            <answer description="Option 4"/>
        </status>
    </statuses>
</labels>

Мой XSL

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <form method="POST" action="new-process.php">
            <div class="mainC">
                <xsl:apply-templates/> 
            </div>
            <input type="submit" name="submit" value="Submit" />
        </form>
    </xsl:template>

    <xsl:template match="options">
        <xsl:for-each select="option"> 

            <div class="columnDiv">
                <h3><xsl:value-of select="@type"/></h3>
                <xsl:apply-templates select="/labels/statuses"/>
            </div>

        </xsl:for-each>
    </xsl:template>

     <xsl:template match="status">
        <xsl:for-each select="."> 
                <label><xsl:value-of select ="@type"/></label>
                <select>
                    <xsl:for-each select="answer"> 
                            <option><xsl:value-of select="@description"/></option>
                    </xsl:for-each>
                </select>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Токовый выход с комментариями к желаемому выходу

<?xml version="1.0" encoding="UTF-8"?>
<form method="POST" action="new-process.php">
    <div class="mainC">
        <div class="columnDiv">
            <h3>Top Text 1</h3>
            <label>Correct</label><select><option>Yes</option><option>No</option></select>
            <label>Error - Type 1</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
            <label>Error - Type 2</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
        </div>
        <div class="columnDiv">
            <h3>Top Text 2</h3>
            <label>Correct</label><select><option>Yes</option><option>No</option></select>
            <label>Error - Type 1</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
            <label>Error - Type 2</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
        </div>
        <div class="columnDiv">
            <h3>Top Text 2</h3>
            <label>Correct</label><select><option>Yes</option><option>No</option></select>
            <label>Error - Type 1</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
            <label>Error - Type 2</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
        </div>

        <!-- \ this is the output that I do no want \ -->
        <label>Correct</label><select><option>Yes</option><option>No</option></select>
        <label>Error - Type 1</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
        <label>Error - Type 2</label><select><option>Option 1</option><option>Option 2</option><option>Option 3</option><option>Option 4</option></select>
        <!-- / this is the output that I do no want / -->

    </div>
    <input type="submit" name="submit" value="Submit"/>
</form>

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

За комментарии, чтобы получить решение, которое вам нужно, вам нужно всего лишь добавить select="/labels/options" к вашему первому утверждению apply-templates. @TimC дает отличное объяснение этого в своем ответе .

Тем не менее, вы также использовали много циклов for-each в своем коде. Обычно с XSL лучше использовать шаблоны в таких сценариях, так как это делает код более чистым *. Вот измененная версия с удаленными петлями: http://xsltfiddle.liberty -development.net / bFDb2BX / 3

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <form method="POST" action="new-process.php">
            <div class="mainC">
                <xsl:apply-templates select="/labels/options"/> 
            </div>
            <input type="submit" name="submit" value="Submit" />
        </form>
    </xsl:template>

    <xsl:template match="options/option">
        <div class="columnDiv">
            <h3><xsl:value-of select="@type"/></h3>
            <xsl:apply-templates select="/labels/statuses"/>
        </div>
    </xsl:template>

     <xsl:template match="status">
            <label><xsl:value-of select ="@type"/></label>
            <select>
                <xsl:apply-templates select="./answer"/>
            </select>
    </xsl:template>

     <xsl:template match="answer">
            <option><xsl:value-of select="@description"/></option>
    </xsl:template>


</xsl:stylesheet>

* Я первоначально заявил, что это также улучшило параллельную обработку; но, как указывает Мартин в комментариях, некоторые движки поддерживают параллельную обработку и для for-each; и я не смог найти никакой документации, подтверждающей мое первоначальное утверждение; так что подозреваю, что это апокриф.

0 голосов
/ 26 апреля 2018

Вы совсем не плохо начали, но теперь вам нужно узнать о XSLT Встроенные правила шаблонов . Это шаблоны, которые будут использоваться, когда в вашем XSLT нет подходящего шаблона.

У вас есть шаблон, соответствующий узлу документа /, в котором вы делаете <xsl:apply-templates />. Это выберет узел label, для которого у вас нет шаблона. Таким образом, шаблон по умолчанию это ...

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

И это выберет узлы options и statuses. У вас есть шаблон, соответствующий options, так что это хорошо, но не один шаблон statuses, поэтому встроенный снова включается.

Но в вашем шаблоне options вы делаете <xsl:apply-templates select="/labels/statuses"/>, что в итоге приводит к тому, что statuses (и дочерние status узлы) выбираются дважды.

Одним из решений является изменение <xsl:apply-templates /> в узле / для явного выбора только options, например, так ...

<xsl:template match="/">
    <form method="POST" action="new-process.php">
        <div class="mainC">
            <xsl:apply-templates select="labels/options"/> 
        </div>
        <input type="submit" name="submit" value="Submit" />
    </form>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...