2012-04-16 4 views
1

나는 다음과 같은 마크 업, 하나 또는 두 아이 TDS에XPath 표현식은 아이에 따라 형제 이행 조건까지, 노드의 형제 자매와 일치하는

<table> 
    <tr> 
     <td> 
     <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
     <td> 
     <p>YYYYYY</p> 
     </td> 
    </tr> 
    </table> 
와 거래 정보 저장소의 믹스와 함께 테이블이

나는이 XSLT에서 중첩 루프, 어떤 XPath는 표현에 넣어 접근하는 가장 좋은 방법은 아마도 사실 추상하면

<AAA> 
    XXX 
    <BBB>YYYYY</BBB> 
    <BBB>YYYYY</BBB> 
    ... 
</AAA> 
<AAA> 
    XXX 
    <BBB>YYYYY</BBB> 
    <BBB>YYYYY</BBB> 
    ... 
</AAA> 
... 

에이를 변환하는 XSLT 1.0을 사용하려고 ??? 아래에 두 개의 TD 자식이 있지만 다음 TR (XXX)까지만 현재 TR (XXX)의 모든 TR 형제를 선택합니다. 나는 얼마나 많은 TD 자녀가 있는지에 따라 XXX 및 YYYYY 포함 노드를 구별합니다. 1 = XXX, 2 = YYYYY. 어떻게이 만을 선택해야합니까 -

<xsl:for-each select="//table/tr"> 
    <xsl:if test="count(td) = '1'"> 
     XXX 
    </xsl:if> 
    <xsl:for-each select="???"> 
     all YYYYY up until the next XXX 
    </xsl:for-each> 
</xsl:for-each> 

내가했다 ":: TR [아이 : TD-형제 다음 [다음 - 형제 : TD]는"하지만 모두가 끝까지 YYYYY로 다음과 일치 XXX와 함께 다음 TR까지?

감사합니다.

답변

1

I. XSLT 1.0 용액 :

<table> 
    <tr> 
     <td> 
      <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>XXX</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
     <td> 
      <p>YYYYYY</p> 
     </td> 
    </tr> 
</table> 

가 원하는 정확한 결과 생산이 XSLT 1.0 변환이 제공된 XML 문서에인가

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kFollowing" match="tr[td[2]]" 
    use="generate-id(preceding-sibling::tr 
            [not(td[2])] 
            [1] 
        )"/> 

<xsl:template match="/*"> 
    <xsl:apply-templates select="tr[not(td[2])]"/> 
</xsl:template> 

<xsl:template match="tr[not(td[2])]"> 
    <AAA> 
    <xsl:value-of select="concat('&#xA;', td/p, '&#xA;')"/> 

    <xsl:apply-templates select="key('kFollowing', generate-id())"/> 
    </AAA> 
</xsl:template> 

<xsl:template match="p"> 
    <BBB><xsl:value-of select="."/></BBB> 
</xsl:template> 
</xsl:stylesheet> 

:

<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 
<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 
<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 

설명하십시오 key

적절한 사용 직전 단일 tr 자식 요소의 generate-id()의 함수로서 제 td 아이 tr 모두를 정의한다.

II. XSLT 2.0 용액 :이 변환은 동일한 XML 문서 (위)에인가

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/*"> 
    <xsl:for-each-group group-starting-with="tr[not(td[2])]" 
     select="tr"> 
    <xsl:apply-templates select="current-group()[1]"/> 
    </xsl:for-each-group> 
</xsl:template> 

<xsl:template match="tr[not(td[2])]"> 
    <AAA> 
    <xsl:value-of select="concat('&#xA;', td/p, '&#xA;')"/> 

    <xsl:apply-templates select="current-group()[position() gt 1]"/> 
    </AAA> 
</xsl:template> 

<xsl:template match="p"> 
    <BBB><xsl:value-of select="."/></BBB> 
</xsl:template> 
</xsl:stylesheet> 

같은 올바른 결과 제조된다 :

<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 
<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 
<AAA> 
XXX 
<BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
    <BBB>YYYYYY</BBB> 
</AAA> 

설명 :

xsl:for-each-groupgroup-starting-with 속성 및 t의 적절한 사용 그는 current-group() 기능을합니다.

+0

정말 철저한 대답을, 정말 감사합니다 :

또 다른 방법은 조건에 일치하는 첫 번째 노드의 순서를 검색 한 다음 해당 위치까지의 노드를 선택하는 서브()를 사용하는 것입니다! – WojtekD

+0

@WojtekD : 환영합니다. –

0

필자가 정확히 요구하는 것을 수행하는 XPath 구조를 갖는 것이 유용 할 것이라고 항상 생각했습니다. 어떤 조건과 일치하는 첫 번째 시퀀스까지의 모든 항목 (및 포함/제외). 나는 이것에 대한 문법을 ​​expr until condition과 같은 것으로 생각했다. saxon : leading()와 같이 요구 사항을 충족시키기 위해 Saxon과 EXSLT에서 고차원 확장 기능을 제공하는 시도가 있습니다. 슬프게도 사양에는 아무 것도 없습니다. XPath 3.0에서는 고차원 함수를 사용하여 쉽게 쉽게 처리 할 수 ​​있습니다.

때때로 그룹화 (xsl : for-each-group)를 사용하여 문제를 해결할 수 있지만 가장 간단하고 가장 우아한 방법은 재귀를 사용하는 것입니다. 즉, 시퀀스의 첫 번째 항목을 처리하는 함수를 작성하고 어떤 조건이 충족되면 다음 항목을 처리하기 위해 자신을 호출합니다.

<xsl:variable name="positions" select=" 
    for $i in 1 to count($seq) 
    return if (my:condition($seq[$i])) then $i else()"/> 
<xsl:apply-templates select="subsequence($seq, 1, $positions[1])"/> 
+0

죄송합니다. XSLT 1.0에 대해 언급 한 것을 볼 수 있습니다. 그것은 당신의 삶을 훨씬 어렵게 만듭니다. –