문제

제작 해야하는 모든 항목을 정의하는 XML 파일을 사용하여 넌트 빌드 스크립트를 작성하는 것보다 XSL을 결합하고 있습니다. 우리는 표준 레이아웃과 핸드 오버 영역에 대한 정의 된 표준을 갖춘 매우 유사한 프로젝트를 보유하고 있으며, 따라서 개발자가 어떻게 해야하는지 정의하는 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 라인 사이에 정의되어 모드/@name 값을 유지하기 위해 정의하여 할 수 있지만 약간 지저분하고 실제로하고 싶은 것은 빌드 모드가 내부에 있도록 Nexting을 뒤집는 것입니다. 항목 루프는 하나의 모드를 빌드하여 다른 모드를 구축합니다. 현재 모든 디버그를 빌드 한 다음 모든 릴리스 빌드를 빌드합니다. 그렇게하기 위해 나는 몇 가지 선언을 받아야 할 것이고 그것은 매우 지저분 해지고 있습니다.

따라서 소스 문서의 요소가 중첩되지 않은 경우 중첩됩니다.

편집하다:

자, 아래에 허용 된 답변이 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>
도움이 되었습니까?

해결책

성공의 열쇠는입니다 사용하지 마십시오 <xsl:for-each> 조금도.

<xsl:template match="/">
  <xsl:apply-templates select="Build/BuildModes/Mode" />
</xsl:template>

<xsl:template match="Build/BuildModes/Mode">
  <exec program="devenv">
    <xsl:apply-templates select="/Build/ItemsToBuild/Item">
      <xsl:with-param name="BuildMode" select="." />
    </xsl:apply-templates>
  </exec>
</xsl:template>

<xsl:template match="Build/ItemsToBuild/Item">
  <xsl:param name="BuildMode" />
  <xsl:attribute name="line">
    <!-- use $BuildMode/@name etc. to build up the command line -->
  </xsl:attribute>
</xsl:template>

다른 팁

컨텍스트 노드를 변경하는 작업을 수행하기 전에 변수에 현재 컨텍스트 노드를 저장하는 핵심 기술은 아마도 핵심 기술이라고 생각합니다. 아래의 예에서 사용하는 기술을 사용하면 작동하는 것이 작동합니다.

많은 XSLT 문제와 마찬가지로 절차 대신 변환을 생각하면 해결하기가 더 쉽습니다. 문제는 실제로 "각각의 고리를 둥지하는 방법"이 아닙니다. "어떻게 변환 하는가? Item 원하는 요소 exec 집단?"

<xsl:template match="/">
   <output>
      <xsl:apply-templates select="/Build/ItemsToBuild/Item"/>
   </output>
</xsl:template>

<xsl:template match="Item">
   <xsl:variable name="item" select="."/>
   <xsl:for-each select="/Build/BuildModes/Mode">
      <exec program="devenv">
         <xsl:attribute name="itemName" select="$item/@name"/>
         <xsl:attribute name="modeName" select="@name"/>
         <!-- and so on -->
      </exec>
   </xsl:for-each>
</xsl:template>

이름이 지정된 템플릿을 사용할 수 있습니다.

<xsl:template name="execute">
  <xsl:param name="mode" />
  <xsl:for-each select="/Build/ItemsToBuild/Item">
   <exec program="devenv">
    <xsl:attribute name="line">
        use $mode and other stuff from Item to build up the command line
    </xsl:attribute>
   </exec>
  </xsl:for-each>
</xsl:template>

그런 다음 전화하십시오.

<xsl:for-each select="/Build/BuildModes/Mode">
 <xsl:call-template name="execute">
  <xsl:with-param name="mode" select="@name" />
 </xsl:call-template>
</xsl:for-each>

이것은 분리하는 데 도움이 될 것이지만 더 이상 명확한 지 확실하지 않습니다.

불행히도, 당신이 그것을 어떻게 보더라도, 당신은 당신이 시도하고 동시에 두 가지 맥락을 얻고 있기 때문에 배관공을해야합니다.

당신은 a를 사용할 수 있습니다 변하기 쉬운 항목 컨텍스트를 저장합니다. 또한 속성 정의를 정리하기위한 속기.

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <someroot>
            <xsl:for-each select="/Build/ItemsToBuild/Item">
                <xsl:variable name="item" select="." />
                <xsl:for-each select="/Build/BuildModes/Mode">
                    <exec program="devenv"
                        item="{$item/@name}" line="{@name}" />
                </xsl:for-each>
            </xsl:for-each>
        </someroot>
    </xsl:template>
</xsl:stylesheet>

결과입니다

<someroot>
    <exec program="devenv" item="item1" line="Debug" />
    <exec program="devenv" item="item1" line="Release" />
    <exec program="devenv" item="item2" line="Debug" />
    <exec program="devenv" item="item2" line="Release" />
</someroot>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top