为什么这个XSL模板呈现/生成2次?

时间:2018-04-26 14:32:24

标签: xml xslt

我今天开始使用xsl进行第一次冒险,希望能够做到这一点"轻松"脚本很快。 现在4小时后,我仍然不知道它为什么会产生2次......

我需要你的帮助才能在我的脚本中找到错误,因为我自己无法找到它......

我正在使用XSL创建基于XML的HTML表单 我基本上有一个自动创建两次的模板。我只想要<div class="columnDiv">中的那个。

屏幕截图 error reasult 屏幕截图显示我想要的内容 achieve

我的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 :(得分:3)

根据评论,只需在您的第一个apply-templates语句中添加select="/labels/options"后即可获得解决方案。 @TimC在his answer中给出了很好的解释。

也就是说,您在代码中也使用了很多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>

*我最初表示这也改善了并行处理;但正如Martin在评论中指出的那样,一些引擎也支持for-each的并行处理;而且我找不到任何文件来支持我原来的陈述;所以怀疑它是伪造的。

答案 1 :(得分:1)

你根本没有开始,但你现在需要了解XSLT的Built in Template Rules。这些是在XSLT中没有匹配模板时使用的模板。

您有一个与文档节点/匹配的模板,您可以在其中执行<xsl:apply-templates />。这将选择您没有模板的label节点。所以默认模板就是这个......

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

这将选择optionsstatuses个节点。您有一个匹配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>