【问题标题】:How to apply or import an XSLT template based on parametre如何应用或导入基于参数的 XSLT 模板
【发布时间】:2013-12-16 15:29:09
【问题描述】:

我正在寻找如何根据 XML 文件中的参数将模板应用于 XML 文件。

XML 文件的格式如下:

<workfile>  
    <query>  
        <some-info-1/>  
        <some-info-2/>  
        <some-info-3/>  
        <some-info-4/>  
        <some-info-5/>  
        <some-info-6/>  
        <some-info-7/>  
        <parameter name="hours-min" value="7" />  
        <parameter name="hours-max" value="9" />  
        <parameter name="output-type" value="type-1" />  
    </query>  
</workfile>

XML 文件由另一个程序生成,需要特定的输出格式,具体取决于参数“output-type”的值。此参数可以出现多次,如果必须同时为多个输出生成结果,则需要一个for-each 循环。

编辑这是一个带有多个输出类型参数的示例:

<workfile>  
    <query>  
        <some-info-1/>  
        <some-info-2/>  
        <some-info-3/>  
        <parameter name="hours-min" value="7" />  
        <parameter name="hours-max" value="9" />  
        <parameter name="output-type" value="type-1" />  
        <parameter name="output-type" value="type-2" />  
        <parameter name="output-type" value="type-3" />  
    </query>  
</workfile>

我想创建一个主模板文件generate-main.xsl,并在该文件中导入/包含其他模板文件(generate-type-1.xsl、generate-type-2.xsl 等)。这些模板中的每一个都必须从根节点 (/) 开始工作。但我在构思如何做到这一点时遇到了问题。

这是我写的generate-main.xslbase:

<xsl:template match="/">
    <results>
        <xsl:for-each select="/workfile/query/parameter[@name='output-type']">
            <xsl:variable name="outputType" select="./@value" />
            <xsl:choose>
                <xsl:when test="$outputType='type-1'">
                    <xsl:call-template name="type-1" />
                </xsl:when>
                <xsl:when test="$outputType='type-2'">
                    <xsl:call-template name="type-2" />
                </xsl:when>
                <xsl:when test="$outputType='type-3'">
                    <xsl:call-template name="type-3" />
                </xsl:when>
                <xsl:when test="$outputType='type-4'">
                    <xsl:call-template name="type-4" />
                </xsl:when>
                <xsl:when test="$outputType='type-5'">
                    <xsl:call-template name="type-5" />
                </xsl:when>
                <xsl:otherwise>
                </xsl:otherwise>
            </xsl:choose>
            </xsl:for-each>
        </results>
    </xsl:template>

    <xsl:template name="type-1">
        <!-- TO DO -->
    </xsl:template>

    <xsl:template name="type-2">
        <!-- TO DO -->
    </xsl:template>

    <xsl:template name="type-3">
        <!-- TO DO -->
    </xsl:template>

    <xsl:template name="type-4">
        <!-- TO DO -->
    </xsl:template>

    <xsl:template name="type-5">
        <!-- TO DO -->
    </xsl:template>
</xsl:stylesheet>

我确实对此进行了研究。例如,Dimitre Novatchev 回答了模板何时位于同一个 XSL 文件 (Applying different XSLT template depending on a parameter) 中的问题,但我没有找到如何使用从根节点工作的导入 XSL 文件来做到这一点。

所以我的问题是:
1) 是否可以将模板包含或导入到主 XSL 文件中,并且仅根据参数调用一个模板(例如,通过在被调用模板中播放包含?)
2) 如果所有包含的模板都可以与根节点一起使用(我假设以&lt;template match="/"&gt; 开头),是否仍然有可能?

任何帮助将不胜感激。

安东·哈里斯

【问题讨论】:

  • 我还找到了如何调用带有参数的模板,以指定根节点(call xslt template with parameter),但我没有看到如何将其应用于被调用的模板。
  • 您能否提供一个包含多个“参数”的输入示例?并指定在这种情况下的预期输出是什么?请注意,“参数”通常是指调用例程在运行时提供给样式表的东西,而不是作为数据的一部分包含在已处理的 XML 中的东西。
  • 参数实际上是一个标签,&lt;parameter&gt;。其他参数不影响调用哪个模板。其他参数包括最短工作时间 (&lt;parameter name="min-hours" value="7" /&gt;)、最长工作时间 (&lt;parameter name="max-hours" value="9" /&gt;) 等。我已经编辑了代码以在示例中包含其他参数。
  • 我的意思是一个带有多个“输出类型”参数的示例。
  • 我用多个输出类型参数编辑了一个示例 XML。

标签: xml templates xslt xslt-2.0


【解决方案1】:

在编译时包含和导入工作,当没有可用的源文档时,因此您无法根据您在数据中找到的内容导入或包含内容(除非您想进入动态样式表生成,我对此表示怀疑这里合适)。

我不清楚为什么不能使用标准的应用模板机制解决问题。替换这个东西:

<xsl:for-each select="/workfile/query/parameter[@name='output-type']">
            <xsl:variable name="outputType" select="./@value" />
            <xsl:choose>
                <xsl:when test="$outputType='type-1'">
                    <xsl:call-template name="type-1" />
                </xsl:when>

<xsl:template name="type-1">
    <!-- TO DO -->
</xsl:template>

(非常不像 XSLT,而且很冗长)

<xsl:apply-templates select="/workfile/query/parameter[@name='output-type']"/>

<xsl:template match="parameter[@name='output-type'][@value='type1']">
<!-- TO DO -->
</xsl:template>

等等

为什么要所有包含的模板都从根节点开始?

【讨论】:

  • 感谢您的回答。此 XSLT 文件是项目的最后一步,其中包括应用于起始 XML 文件的 XSLT 文件和对 Web 服务的调用。结果(由参数'output-type'指定)取决于起始查询信息(例如,小时总和可能超出范围,节点中规定了最大和最小小时数,并且需要生成错误消息),以及在执行此 XSLT 文件之前获取的信息。希望这能回答你的问题。这就是为什么称为模板化需要访问根节点的原因。
  • 另外,我正在寻找包含/导入,因为我们是两个人从事该项目,这是为了避免大量复制/粘贴代码。 (单独评论,否则之前的评论会太长。)
  • 在查看了代码并考虑了您上一个问题的答案之后,我相信我一直在过度复杂化我想做的事情。所以我将减少臃肿,并且应该能够达到结果。我会将此答案标记为正确,因为它使我得到了我想要的。
【解决方案2】:

我认为这里有两个问题:

  1. 你能做你想做的事吗?
  2. 你应该做你想做的事吗?

第一个问题的答案是肯定的。您可以在主样式表中包含其他样式表,并以与主样式表中的模板相同的方式调用它们的模板。并且每个模板都可以选择它需要选择的任何东西——包括从根开始,如果需要的话。

请注意,包含的样式表总是包含在内 - 与运行时发生的情况无关。您可以根据输入决定是否使用它们;但他们会一直在那里。

第二个问题的答案比较难,因为描述太抽象了。我怀疑您可以从单个“输出”模板中获得更多里程,多次调用 - 每次使用不同的参数。然后使用模板内部choose 元素来生成适当的输出。

【讨论】:

  • 你能告诉我描述太抽象,以便我提供更多细节吗?
  • @AntonH:我的意思是我们不知道不同模板的作用。我们甚至不知道“some-info”下的数据类型。这是一个策略问题,当我们真的不知道自己在处理什么时,很难说最好的策略是什么。
  • 我不知道知道模板做什么,也不指定 节点中的其他信息有什么帮助,因为模板 自己 工作,我的问题没有考虑其他信息()。我的问题是关于调用其他文件中包含的模板。
猜你喜欢
  • 2016-08-06
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多