需要存储在 for-each 中创建的不属于 XML 文件的局部变量

Need to store local variables created in for-each that aren't a part of XML file

我正在使用 XSLT 将 2 个 XML 文件转换为 C 代码 (XSLT 2.0)。

目标是生成 .c 文件所需的 #include(可能很多)。

我需要在两个不同的地方查找 #include 名称的可变部分:一个可以直接从一个 XML 文件中读取,但第二个需要搜索另一个文件一旦我们找到第一个(两个都是生成的 XML 文件,是继承代码!)。

    <xsl:for-each select="/root/eventDoc/event/parameterList/parameter">
        <xsl:variable name="name" select="@name"/>
        <xsl:variable name="module" select="@module"/>
        <xsl:variable name="refModule" select="eventgen:ref-module-lookup($name, $module)"/>

目前我只是像这样在包含中打印 $module$refModule(通过删除我当前的工作来简化以避免重复):

    <xsl:text>
    #include "agent/gen/</xsl:text><xsl:value-of select="concat(fn:lower-case(translate($module, '-', '_')),'.h')"/><xsl:text>"</xsl:text>

这工作正常,但我想摆脱不可避免的重复。 如果我只是简单地编写 C 代码,我会创建一个数组并添加每个唯一的 $module$refModule,然后遍历它并打印出来。

我的第一个方法是使用 preceding::parameter/@module 来避免重复,问题是 preceding::parameter/@refModule 不存在,因为它不属于这个 XML 文件! preceding::parameter/$refModule 也没有用(XSLT 中的变量范围不是 100% 清楚)。

我想我可以处理独特的部分,但我的问题是如何存储这些非XML值,以便我可以在 for-each 并打印出来?模板?也许我根本不需要存储?

注意:我可以提供 XML 输入,但我认为这对我的问题没有帮助(让我知道)

谢谢!

编辑:虽然已经解决,但为遇到类似问题的任何不幸的人添加一些附加信息。

输入XML一个:

<event name="PolicyError">
<!-- list of parameters -->
  <parameterList>
      <parameter
        name="Index" module="COMPANY-TEAM-NG-MIB"
      />        
      <parameter
        name="PolicyId" module="COMPANY-TEAM-NG-MIB"
      />
  </parameterList>
</event>

期望的输出:

#include "agent/gen/company_team_ng_mib.h"

为了简单起见,我省略了 eventgen:ref-module-lookup 函数和第二个 XML 文件,但它基本上使用给定的 namemodule查找定义了 name 的根 module (refModule)

你没有给出我可以用来测试的例子,但是如果你可以将所有可能的值放入一个序列中,那么你可以使用 distinct-values 删除重复项,例如:

<xsl:variable name="moduleNames" select="distinct-values(/root/eventDoc/event
  /parameterList/parameter/(@module, eventgen:ref-module-lookup(@name, @module)))"/>

<xsl:for-each select="$moduleNames">
  <xsl:value-of select="concat('&#10;#include &quot;agent/gen/',
                               lower-case(translate(., '-', '_')),
                               '.h&quot;')"/>
</xsl:for-each>

请注意,distinct-values 不提供任何排序​​保证。如果这是一个问题(即您需要 #include 指令以与 XML 中的参数相同的顺序出现)那么您可以使用 for-each-group 代替:

<xsl:variable name="moduleNames" select="/root/eventDoc/event
  /parameterList/parameter/(@module, eventgen:ref-module-lookup(@name, @module))"/>

<xsl:for-each-group select="$moduleNames" group-by=".">
  <xsl:value-of select="concat('&#10;#include &quot;agent/gen/',
                               lower-case(translate(., '-', '_')),
                               '.h&quot;')"/>
</xsl:for-each-group>

处理各个组的结果是保证按照组在输入序列中首次提及的顺序输出。

为了完整起见,这是我最终采用的解决方案。 Ian 已经完成了 99% 的解决方案,我只需要按字母顺序对 #includes 进行排序。

  <xsl:variable name="moduleNames" select="distinct-values(/root/eventDoc/event/parameterList/parameter/(@module, eventgen:ref-module-lookup(@name, @module)))"/>
  <xsl:for-each select="$moduleNames">
    <xsl:sort select="." />
    <xsl:value-of select="concat('&#10;#include &quot;agent/gen/',
                           lower-case(translate(., '-', '_')),
                           '.h&quot;')"/>
  </xsl:for-each>