调用包含的模板时“If-element”没有反应

Posted

技术标签:

【中文标题】调用包含的模板时“If-element”没有反应【英文标题】:"If-element" does not react when calling included template 【发布时间】:2021-08-10 03:35:55 【问题描述】:

我希望构建一个简单的逻辑来让用户定义应该调用哪些模板。该代码说明了一个最小化的示例。当有许多模板时,该设置非常有用,例如我正在构建的输出是大约 2.600 行 Xhtml 代码。那么能够排除几个模板而只关注其中一些模板是非常好的。

我已经成功创建了上述设置(以前),将 XML 作为源文件和模块化代码。我怀疑这是我将 JSON 作为源文件的设置以及导致问题的代码改编。

下面的代码应该允许用户将变量“build-with-books”从 0 切换到 1,如果设置为 1,“if”元素应该调用包含的模板。

我确信有许多“更智能”的方法可以解决我的需求。目前我只是想了解为什么我的代码不遵循打开/关闭元素构建的所需逻辑。

XSLT fiddle 已失效,所以我将代码粘贴到下面:

数据:

<data>

  "books": 
    "Wonderland": 43
  ,
  "beverage": 
    "Falcon": 12
  

</data>

principal.xsl:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ix="http://www.example.com/1"
  xmlns:xbrli="http://www.example.com/2"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="fn"
  expand-text="yes"
>

  <xsl:output method="xml" indent="yes"/>

  <!-- Block all data that has no user defined template -->
  <xsl:mode on-no-match="shallow-skip"/>

  <!-- Includes -->
  <xsl:include href="books.xsl"/>

  <!-- Module selector -->
  <xsl:variable name="build-with-books">0</xsl:variable>

  <!-- Attribute-sets -->
  <xsl:attribute-set name="books">
    <xsl:attribute name="category">Adventure</xsl:attribute>
  </xsl:attribute-set>

  <!-- Main template -->

  <xsl:template match="data">

      <!-- Parse JSON to XML, results in XML map -->
      <xbrli:xbrl>
        <xsl:apply-templates select="json-to-xml(.)/*"/>
      </xbrli:xbrl>

      <!-- Call template -->    
      <xsl:if test=" $build-with-books = '1' ">
        <xsl:call-template name="books"/>
      </xsl:if>

  </xsl:template>

</xsl:transform>

支持模块:books.xsl

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ix="http://www.example.com/1"
  xmlns:xbrli="http://www.example.com/2"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="fn"
  expand-text="yes"
>

<xsl:output method="xml" indent="yes"/>

<!-- Create elements  -->

<xsl:template name="books" match="*[@key = 'books']//*[@key and not(*)]">
    <xsl:element name="ix:@key" use-attribute-sets="books">.</xsl:element>
</xsl:template>

</xsl:transform>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:ix="http://www.example.com/1" xmlns:xbrli="http://www.example.com/2">
   <ix:Wonderland category="Adventure">43</ix:Wonderland>
</xbrli:xbrl>

变量“build-with-books”设置为 0 时的预期结果

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:ix="http://www.example.com/1" xmlns:xbrli="http://www.example.com/2">
</xbrli:xbrl>

变量“build-with-books”设置为 1 时的预期结果

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:ix="http://www.example.com/1" xmlns:xbrli="http://www.example.com/2">
   <ix:Wonderland category="Adventure">43</ix:Wonderland>
</xbrli:xbrl>

【问题讨论】:

如果从books 模板中删除match 会发生什么?我猜是因为您将模板应用于来自json-to-xml() 的所有结果元素,所以该模板仍然匹配。 @DanielHaley,如果我从书籍模板中删除匹配项,并将变量“build-with-books”保持为零,则输出不会使用元素“Wonderland”构建。这是正确的行为,但如果我也将“build-with-book”更改为 1,则完整的输出为空。 【参考方案1】:

开始

从 principal.xsl 中删除这部分:(调用模板使用当前上下文,这仍然是您在数据上的匹配项)

  <!-- Call template -->    
  <xsl:if test=" $build-with-books = '1' ">
    <xsl:call-template name="books"/>
  </xsl:if>

并从中删除@name 属性

<xsl:template name="books" match="*[@key = 'books']//*[@key and not(*)]">

选项:1

将books.xls 中的匹配模板更改为如下所示(它将直接使用您的全局$build-with-books

  <xsl:template match="*[$build-with-books='1'][@key = 'books']//*[@key and not(*)]">
    <xsl:element name="ix:@key" use-attribute-sets="books">.</xsl:element>
  </xsl:template>

选项:2

在您的 principal.xsl 中使用xsl:next-match:(它将首先使用具有更高优先级的模板来检查全局$build-with-books

添加这个:

  <xsl:template match="*[@key = 'books']" priority="10">
    <xsl:if test="$build-with-books='1'">
      <xsl:next-match/>
    </xsl:if>
  </xsl:template>

【讨论】:

以上是关于调用包含的模板时“If-element”没有反应的主要内容,如果未能解决你的问题,请参考以下文章

调用 StreamController.sink.add 时 StreamBuilder 没有反应

c# datagrid模板列checkbox,运行点击没有反应,checked为假.

Ajax 调用不更新模板 django

没有模板的 vuejs 反应性

使用 get API 调用反应全局状态/道具(没有 Redux)

React - 每当更新反应上下文中的状态时如何调用函数?