2010-11-18 4 views
0

이미 처리 된 노드의 처리를 피할 수있는 방법이 있습니까?이미 처리 된 노드의 스킵 처리

입력 XML

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <node1>node1.1</node1> 
    <node2>node2.1</node2> 
    <node2>node2.2</node2> 
    <node1>node1.2</node1> 
</root> 

XSL 당신이 볼 수 있듯이

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="root"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="node1"> 
     [Node1]:<xsl:value-of select="."></xsl:value-of> 
     <xsl:apply-templates select="following-sibling::node2"/> 
     [End node1] 
    </xsl:template> 

    <xsl:template match="node2"> 
      [Node2]:<xsl:value-of select="."></xsl:value-of> 
    </xsl:template> 

</xsl:stylesheet> 

출력

<?xml version="1.0" encoding="UTF-8"?> 

     [Node1]:node1.1 
      [Node2]:node2.1 
      [Node2]:node2.2 
     [End node1] 

      [Node2]:node2.1 

      [Node2]:node2.2 

     [Node1]:node1.2 
     [End node1] 

템플릿 <xsl:template match="node2">은 node2 요소마다 두 번 적용됩니다. node1 템플릿에서 한 번, XSLT 프로세서가 node2 요소를 변형 할 때 두 번 적용됩니다.

두 번째로 xsl:template match="node2"을 적용하는 것을 피하는 해결책이 있습니까? node2에 대한 템플릿을 처리 한 직후 node2 처리를 중지해야합니다.

중요 이 예제는 좀 더 복잡한 유스 케이스의 에뮬레이션 일뿐입니다. 이것은 루트 요소 처리를위한 템플릿을 수정할 수 없다는 추가 제한이 있음을 의미합니다.

요소 처리를 중지하거나 다른 요소로 처리를 이동하는 방법이 있는지 알고 싶습니다.

+0

그럼 언제 * *은'node2' 템플릿을 적용해야 하는가? 'node1' 요소 앞에 나오는'node2' 요소에만 해당합니까? – AakashM

답변

3

mode을 사용하여 사용할 템플릿의 이름을 지정할 수 있습니다.

select이없는 apply-templates 호출을 처리하면서 아무 것도 출력하지 않는 빈 캐치 올 노드를 만들 수 있습니다. 당신이 필요

다음 스타일 시트 출력 :

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="root"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="node1"> 
     [Node1]:<xsl:value-of select="."></xsl:value-of> 
     <xsl:apply-templates select="following-sibling::node2" mode="fromNode1"/> 
     [End node1] 
    </xsl:template> 

    <xsl:template match="node2" mode="fromNode1"> 
      [Node2]:<xsl:value-of select="."></xsl:value-of> 
    </xsl:template> 

    <xsl:template match="node2"></xsl:template> 
</xsl:stylesheet> 

주 끝에 빈 모덜리스 템플릿 및 템플릿에 추가 mode 속성과 apply-templates를 호출.

+0

Ooh 나는 모드 강한 솔루션을 고려하지 않았습니다. – annakata

+0

+1 좋은 해결책입니다. –

+0

이것은 'node1'의 앞에 그룹화하지 않음에 유의하십시오. 따라서 노드 2는 궁극적으로 한 번 이상 –

0

XSLT는 상태를 추적하지 않으며 모든 적용 템플릿, for-each 등은 잠재적으로 "중복"결과를 생성하지만 스타일 시트 디자인에는 완전히 문제가 있습니다. 한 번 이상 노드를 "처리"하여 적절한 템플리트를 변경하고 선택해야하므로 두 번 이상 처리되지 않습니다.

예를 들어 설명해 보면 매우 사소한 것이지만, 귀하의 사례가 그다지 대표 적이 지 않다고 말하면 문제가있을 경우 더 완벽한 내용을 게시 할 것을 제안합니다.

1

이 스타일 :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:key name="kNode2ByPrecedingNode1" match="node2" 
      use="generate-id(preceding-sibling::node1)"/> 
    <xsl:template match="root"> 
     <xsl:apply-templates select="node1"/> 
    </xsl:template> 
    <xsl:template match="node1"> 
     <xsl:value-of select="concat('[Node1]: ',.,'&#xA;')"/> 
     <xsl:apply-templates select="key('kNode2ByPrecedingNode1', 
             generate-id())"/> 
     <xsl:text>[End node1]&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:template match="node2"> 
     <xsl:value-of select="concat('&#x9;[Node2]: ',.,'&#xA;')"/> 
    </xsl:template> 
</xsl:stylesheet> 

출력 :

[Node1]: node1.1 
    [Node2]: node2.1 
    [Node2]: node2.2 
[End node1] 
[Node1]: node1.2 
[End node1] 

: 두 가지 문제 : 당신이 모든 노드 아이들에게 템플릿을 적용하여 root 규칙에서 한 번 이상 node2 더 처리, 및 node1 규칙으로부터; 그리고 following-sibling::node2 표현식은 node2 다음에 어떤 것이 따르는 지 구별하지 않습니다. node1.

편집 : 당신이 root 규칙 템플릿을 적용하는 방법을 변경할 수없는 경우, 다음 프로세스 모드를 필요 였는지를을 건너 뛸 것 :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:key name="kNode2ByPrecedingNode1" match="node2" 
      use="generate-id(preceding-sibling::node1)"/> 
    <xsl:template match="root"> 
     <xsl:apply-templates/> 
    </xsl:template> 
    <xsl:template match="node1"> 
     <xsl:value-of select="concat('[Node1]: ',.,'&#xA;')"/> 
     <xsl:apply-templates select="key('kNode2ByPrecedingNode1', 
             generate-id())" 
          mode="output"/> 
     <xsl:text>[End node1]&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:template match="node2"/> 
    <xsl:template match="node2" mode="output"> 
     <xsl:value-of select="concat('&#x9;[Node2]: ',.,'&#xA;')"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

+1의 좋은 해결책이 될 수 있습니다. –