2011-11-16 3 views
3

내 XML은 매우 평평하고, 여기에 예입니다 :이 표시되는지중첩 여러 XSLT 템플릿 조건부

<Rows> 
    <Row> 
    <ProjectID>1000</ProjectID> 
    <Phase>Initiation</Phase> 
    <ID>1</ID> 
    <Name>Work item 1</Name> 
    <Master>1</Master> 
    </Row> 
    <Row> 
    <ProjectID>1000</ProjectID> 
    <Phase>Initiation</Phase> 
    <ID>2</ID> 
    <Name>Work item 2</Name> 
    <Master>1</Master> 
    </Row> 
    <Row> 
    <ProjectID>1000</ProjectID> 
    <Phase>Closing</Phase> 
    <ID>3</ID> 
    <Name>Work item 3</Name> 
    <Master>3</Master> 
    </Row> 
    <Row> 
    <ProjectID>1000</ProjectID> 
    <Phase>Closing</Phase> 
    <ID>4</ID> 
    <Name>Work item 4</Name> 
    <Master>3</Master> 
    </Row> 
    <Row> 
    <ProjectID>1000</ProjectID> 
    <Phase>Closing</Phase> 
    <ID>5</ID> 
    <Name>Work item 5</Name> 
    <Master>4</Master> 
    </Row> 
</Rows> 

그리고 그들은 그런 방법으로 중첩 될 필요가 같은 :

**Initiation** 
Work item 1 
    Work item 2 
**Closing** 
    Work item 3 
    Work item 4 
     Work item 5 

지금 나는 ProjectID, Phase, Name을위한 템플릿을 가지고 있습니다 (예를 들어, 실제 템플릿은 비교적 큽니다). ProjectID 템플릿, 그룹 및 루프 순으로 시작한 다음 순차적으로 그룹화하고 루프합니다. (그래서, 프로젝트별로 단계별로 모든 이름의 목록을 얻습니다.) 그것은 단지 2 단계 (작업 항목 1과 2)는 훌륭하지만 3 단계 (작업 항목 5)는 나를 잃어 버렸습니다.

는 지금은 (실제 코드 여기에) 이름 템플릿에 일치하는 모든 마스터 필드를 반복하려고 :

<xsl:template name="Deliverable"> 
    <!-- 
Parent == True && Lone == True -> Impossible 
Parent == True && Lone == False -> Parent 
Parent == False && Lone == False -> Child 
Parent == False && Lone = True -> Single deliverable --> 

    <xsl:param name="parent" /> 
    <xsl:param name="lone" /> 

    <xsl:variable name="Parent"> 
     <xsl:choose> 
     <xsl:when test="count(key('project-phase-deliverables', concat(ProjectNo, '|', Phase, '|', IDField2))) > 1"> 
      1 
     </xsl:when> 
     <xsl:otherwise> 
      0 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="ID"><xsl:value-of select="generate-id(IDField1)" /></xsl:variable> 

    <tr> 
     <xsl:choose> 
     <!-- JS for parent deliverable --> 
     <xsl:when test="$Parent = 'True'"> 
      <xsl:attribute name="ID"> 
      <xsl:value-of select="$ID"/> 
      </xsl:attribute> 
      <script>$('#<xsl:value-of select="$ID"/>').click(function() { $('.<xsl:value-of select="IDField2"/>').toggle(); });</script> 
     </xsl:when> 
     <!-- Coloring/attributes for children --> 
     <xsl:when test="$parent = 'False' and $lone='False'"> 
      <xsl:attribute name="style">background: #DEDEFF; display: none;</xsl:attribute> 
      <xsl:attribute name="class"> 
      <xsl:value-of select="IDField2"/> 
      </xsl:attribute> 
     </xsl:when> 
     </xsl:choose> 

     <td class="doWhite" style="width: 15px; height: 24px; text-align:right; border-right:none;"> 
     <p class="normal"> 
      <!-- Parent deliverable expander arrow --> 
      <xsl:if test="$Parent = 1"> 
      <span class="Expander">&#9654;</span> 
      </xsl:if> 
     </p> 
     </td> 
     <td class="doWhite" style="width: 200px; height: 24px; border-left:none;"> 
     <p class="normal"> 
      <!-- Child deliverable diamond --> 
      <xsl:if test="$parent = 'False' and $lone = 'False'"> 
      <span class="Expander">&#9670; </span> 
      </xsl:if> 
      <xsl:value-of select="ItemDescription"/> 
     </p> 
     </td> 
     <td class="doWhite" style="width: 130px; height: 24px"> 
     <p class="normal"> 
      <xsl:value-of select="Owner"/> 
     </p> 
     </td> 
     <td style="width: 60px; height: 24px"> 
     <xsl:call-template name="status"/> 
     </td> 
     <td class="doWhite"> 
     <p class="normal"> 
      <xsl:value-of select="ItemNotes"/> 
     </p> 
     </td> 
    </tr> 
    <xsl:if test="$Parent = 1"> 
     <xsl:for-each select="key('project-phase-deliverables', concat(ProjectNo, '|', Phase, '|', IDField2))[position()!=1]"> 
     <!-- this doesn't recurse properly :(--> 
     <xsl:call-template name="Deliverable" /> 
     </xsl:for-each> 
    </xsl:if> 
    </xsl:template> 

을 그리고 당신은 기대할 수로, 그 밖의 무한와 시간을 반복합니다. 내 문제에 대한 적용 - 템플릿을 사용할 수 있지만 다른 필드 (단계 및 ProjectID)를 효과적으로 그룹화하는 데 어떻게 사용할 수있는 것 같은 기분이 들까?

답변

3

귀하의 요구 사항을 이해하지 못했지만, 여기에 지나치게 복잡하게 보이는 것 같습니다.

우선, 나는 단계으로 생각합니다. 당신은 할 수

<xsl:apply-templates 
    select="//Row[generate-id() = generate-id(key('Phase', Phase)[1])]" 
    mode="first" /> 

는 현재 행의 '아이'를 얻으려면 : 그래서 키과 같이 설정 :

<xsl:key name="Phase" match="Row" use="Phase" /> 

그래서 같이 각 단계에서 최상위 일치 재귀 행을 요소

<xsl:apply-templates 
    select="//Row[Phase=current()/Phase][Master=current()/ID][Master != ID]" /> 

그래서

에 맞게 템플릿을 호출 주어진 t

당신이 출력 HTML하려는 경우
<Rows> 
    <Phase name="Initiation"> 
     <Row> 
     <ProjectID>1000</ProjectID> 
     <Phase>Initiation</Phase> 
     <ID>1</ID> 
     <Name>Work item 1</Name> 
     <Master>1</Master> 
     <Row> 
      <ProjectID>1000</ProjectID> 
      <Phase>Initiation</Phase> 
      <ID>2</ID> 
      <Name>Work item 2</Name> 
      <Master>1</Master> 
     </Row> 
     </Row> 
    </Phase> 
    <Phase name="Closing"> 
     <Row> 
     <ProjectID>1000</ProjectID> 
     <Phase>Closing</Phase> 
     <ID>3</ID> 
     <Name>Work item 3</Name> 
     <Master>3</Master> 
     <Row> 
      <ProjectID>1000</ProjectID> 
      <Phase>Closing</Phase> 
      <ID>4</ID> 
      <Name>Work item 4</Name> 
      <Master>3</Master> 
      <Row> 
       <ProjectID>1000</ProjectID> 
       <Phase>Closing</Phase> 
       <ID>5</ID> 
       <Name>Work item 5</Name> 
       <Master>4</Master> 
      </Row> 
     </Row> 
     </Row> 
    </Phase> 
</Rows> 

,이 출력해야 다음 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="yes"/> 
    <xsl:key name="Phase" match="Row" use="Phase"/> 

    <xsl:template match="/"> 
     <body> 
     <xsl:apply-templates select="//Row[generate-id() = generate-id(key('Phase', Phase)[1])]" mode="first"/> 
     </body> 
    </xsl:template> 

    <xsl:template match="Row" mode="first"> 
     <h1> 
     <xsl:value-of select="Phase"/> 
     </h1> 
     <ul> 
     <xsl:apply-templates select="key('Phase', Phase)[Master = ID]"/> 
     </ul> 
    </xsl:template> 

    <xsl:template match="Row" name="Row"> 
     <li> 
     <xsl:value-of select="Name"/> 
     <xsl:if test="//Row[Phase=current()/Phase][Master=current()/ID][Master != ID]"> 
      <ul> 
       <xsl:apply-templates select="//Row[Phase=current()/Phase][Master=current()/ID][Master != ID]"/> 
      </ul> 
     </xsl:if> 
     </li> 
    </xsl:template> 
</xsl:stylesheet> 

을 시도 : 그는 샘플 XML에 적용 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="Phase" match="Row" use="Phase"/> 

    <xsl:template match="/"> 
     <Rows> 
     <xsl:apply-templates select="//Row[generate-id() = generate-id(key('Phase', Phase)[1])]" mode="first"/> 
     </Rows> 
    </xsl:template> 

    <xsl:template match="Row" mode="first"> 
     <Phase name="{Phase}"> 
     <xsl:apply-templates select="key('Phase', Phase)[Master = ID]"/> 
     </Phase> 
    </xsl:template> 

    <xsl:template match="Row" name="Row"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:apply-templates select="//Row[Phase=current()/Phase][Master=current()/ID][Master != ID]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

다음, 다음 출력 다음의 HTML

<body> 
    <h1>Initiation</h1> 
    <ul> 
     <li>Work item 1 
     <ul> 
      <li>Work item 2</li> 
     </ul> 
     </li> 
    </ul> 
    <h1>Closing</h1> 
    <ul> 
     <li>Work item 3 
     <ul> 
      <li>Work item 4 
       <ul> 
        <li>Work item 5</li> 
       </ul> 
      </li> 
     </ul> 
     </li> 
    </ul> 
</body> 
+0

그래서 e @ * | node()는 현재 노드의 모든 요소를 ​​반환합니까? 특정 요소 만 반환 할 수 있습니까? 단순히 을 수행하는 것만으로는 효과가없는 것 같습니다. – Parker

+0

원본 XSLT에서 오류가 수정되었지만 실제로 출력 할 을 나타내는 HTML을 출력하는 다른 샘플도 포함되었습니다. –

+0

굉장해, 이제 알겠습니다! 감사! – Parker