我将 XSL 放在一起,而不是使用定义所有需要构建的项目的 XML 文件作为输入来创建 NAnt 构建脚本。我们有许多非常相似的项目,它们具有标准布局和已定义的移交区域标准,因此拥有一个定义开发人员想要发生的事情而不是描述需要如何完成的 XML 文件将极大地帮助构建服务的采用。
我想在产品构建 XML 文件中尽早定义要使用的构建模式,即
<Build>
<BuildModes>
<Mode name="Debug" />
<Mode name="Release" />
</BuildModes>
<ItemsToBuild>
<Item name="first item" .... />
<Item name="second item" .... />
</ItemsToBuild>
</Build>
我想要一个
<xsl:for-each select="/Build/BuildModes/Mode">
<xsl:for-each select="/Build/ItemsToBuild/Item">
<exec program="devenv">
<xsl:attribute name="line">
use the @name from the Mode and other stuff from Item to build up the command line
</xsl:attribute>
</xsl:for-each>
</xsl:for-each>
现在,我可以通过在两条 for-each 行之间定义一个来保存 Mode/@name 值,但这有点混乱,我真正想要做的是翻转下一个,以便构建模式在里面Item 循环,因此它先构建一种模式,然后再构建另一种模式。目前它将构建所有调试,然后构建所有发布版本。要做到这一点,我必须声明几个,这变得非常混乱。
所以当源文档中的元素没有嵌套时它是嵌套的。
编辑:
好的,正如下面接受的答案所示,在大多数情况下使用 for-each 是一个坏主意,我已将此示例改写为以下示例。略有不同,因为我使用的架构已针对上述帖子进行了简化,但您明白了。
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="/BuildDefinition">
<xsl:apply-templates select="/BuildDefinition/VS2008SLN/DeploymentProject"/>
</xsl:template>
<xsl:template match="/BuildDefinition/VS2008SLN/DeploymentProject">
<xsl:apply-templates select="/BuildDefinition/BuildModes/Mode">
<xsl:with-param name="BuildTarget" select="." />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/BuildDefinition/BuildModes/Mode">
<xsl:param name="BuildTarget" />
<exec program="devenv"> <!-- not the real call, but for example purposes -->
<xsl:attribute name="ProjectName" select="$BuildTarget/@ProjectName"/>
<xsl:attribute name="SolutionName" select="$BuildTarget/../@SolutionName" />
<xsl:attribute name="ModeName" select="@name"/>
</exec>
</xsl:template>
</xsl:stylesheet>
这是它运行的架构
<BuildDefinition Version="1.0">
<BuildModes>
<Mode name="Debug" />
<Mode name="Release" />
</BuildModes>
<VS2008SLN
SolutionName="MySolution"
SolutionDirectory="Visual Studio 2008\MySolution">
<DeploymentProject
ProjectName="MyDeploymentProject"
DeploymentTargetDirectory="EndsUpHere"
DeploymentManifestName="AndCalledThisInTheDocumentation" />
</VS2008SLN>