2012-10-01 2 views
1

나는 xslt에서 break 문이없고 내 문제를 해결하는 방법을 모른다는 것을 알고 있습니다.xslt foreach and break

 <tag name="param" /> 
     <tag name="Token" /> 
     <tag name="Token" /> 
     <tag name="Token" /> 
     <tag name="param" /> 
     <tag name="Token" /> 
     <tag name="param" /> 
     <tag name="Token" /> 
     <tag name="Token" /> 
     <tag name="Token" /> 
     <tag name="return"/> 

매개 변수는 다음 PARAM 전에 모든 토큰으로 그룹화해야합니다. 내가 어떻게 할 수 있니?

출력은 다음과 같이해야합니다 :

param 
    Token 
    Token 
    Token 
param 
    Token 
param 
    Token 
    Token 
    Token 

답변

5

이는 "비 PARAM"요소와 일치하는 열쇠가 될 것이다 달성하는 또 다른 방법,

<xsl:key 
    name="params" 
    match="tag[@name!='param']" 
    use="generate-id(preceding-sibling::tag[@name='param'][1])" /> 

그리고 최초의 가장 앞 PARAM 요소별로 그룹화, 당신은 당신의 "PARAM을 일치시켜 시작할 것 "요소

<xsl:apply-templates select="tag[@name='param']" /> 

그리고 당신은, 당신은 다음 키

<xsl:apply-templates select="key('params', generate-id())" /> 
를 사용하여 그룹의 관련 태그를 선택할 수에 맞게 각각에 대해 (루트 lelement 가정) 샘플 XML에 적용 할 때

는 다음과 같은 출력

param 
- Token 
- Token 
- Token 
param 
- Token 
param 
- Token 
- Token 
- Token 
- return 

당신은 당신이 할 수 있었던 "수익"요소를 원하지 않는 경우입니다 다음 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" /> 
    <xsl:key name="params" match="tag[@name!='param']" use="generate-id(preceding-sibling::tag[@name='param'][1])" /> 

    <xsl:template match="/*"> 
     <xsl:apply-templates select="tag[@name='param']" /> 
    </xsl:template> 

    <xsl:template match="tag[@name='param']"> 
     <xsl:text>param&#10;</xsl:text> 
     <xsl:apply-templates select="key('params', generate-id())" /> 
    </xsl:template> 

    <xsl:template match="tag"> 
     <xsl:value-of select="concat(' - ', @name, '&#10;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

시도 다른 템플릿을 추가하여 일치시킨 다음 무시하십시오.

3

는 XSLT 2.0에서는이 쉬운 것입니다, for-each-group를 사용하지만, XSLT 1.0에서 덜 간단합니다. 그룹을 구분하는 한 가지 방법은 다음과-형제에게 param 태그 계산하는 것입니다 : 여기

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

    <xsl:output method="text"/> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="*/tag[@name = 'param']" /> 
    </xsl:template> 

    <xsl:template match="tag[@name = 'param']"> 
    <xsl:text>param&#x0a;</xsl:text> 
    <xsl:apply-templates select="following-sibling::tag[@name = 'Token'] 
     [count(following-sibling::tag[@name='param']) 
     = count(current()/following-sibling::tag[@name='param'])]" /> 
    </xsl:template> 

    <xsl:template match="tag[@name = 'Token']"> 
    <xsl:text>&#x09;Token&#x0a;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

우리는 우리가 시작 paramparam 태그를 다음과 같은 수를 가지고있는 Token 태그를 선택하고를, 사람들을, 즉 그 다음 매개 변수 앞에 나타납니다. 이것은 태그의 수가 O (N) 인 다소 비효율적입니다.

<xsl:template match="tag[@name = 'param']"> 
    <xsl:text>param&#x0a;</xsl:text> 
    <xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" /> 
</xsl:template> 

<xsl:template match="tag[@name = 'Token']"> 
    <xsl:text>&#x09;Token&#x0a;</xsl:text> 
    <xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" /> 
</xsl:template> 

여기 param 템플릿이 에 템플릿을 적용보다 효율적인 접근 방법은 각 토큰은 다음 PARAM 전에 마지막 토큰이 있는지 확인하기 위해 "예견"가진, 꼬리 재귀 템플릿을 사용하는 것입니다 먼저 Token을 따르고 Token 템플릿은 첫 번째 다음 형제가 다른 Token인지 여부를 확인하고, 그렇다면 재귀 적으로 템플릿을 적용합니다.

+0

+1 두 번째 해결 방법은 "형제 재귀"라고도합니다. 거의 필요하지 않은 XSLT 2.0에서도이 기법을 마스터 할 가치가 있습니다. –