需要存储在 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 文件,但它基本上使用给定的 name
和 module
查找定义了 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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</xsl:for-each>
我正在使用 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 文件,但它基本上使用给定的 name
和 module
查找定义了 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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</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(' #include "agent/gen/',
lower-case(translate(., '-', '_')),
'.h"')"/>
</xsl:for-each>