2014-10-08 4 views
0

내 XML :어떻게 특정 노드의 레벨을 찾을 수

<menu> 
    <item id=1> 
    <item id=1.1> 
     <item id=1.1.1> 
     <item id=1.1.1.1> 
     <item id=1.1.1.2> 
     <item id=1.1.1.3> 
     </item> 
    </item> 
    <item id=1.2> 
     <item id=1.2.1> 
     <item id=1.2.1.1> 
     <item id=1.2.1.2> 
     <item id=1.2.1.3> 
     </item> 
    </item> 
    </item> 
</menu> 

그리고 내 XSLT :

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

<xsl:param name="menuId"/> 

<xsl:template match="*"> 
    <xsl:if test="descendant-or-self::*[@id=$menuId]"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates /> 
     </xsl:copy> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="item"> 
    <xsl:if test="descendant-or-self::*[@id=$menuId] | 
           parent::*[@id=$menuId] | 
           preceding-sibling::*[@id=$menuId] | 
           following-sibling::*[@id=$menuId] | 
           preceding-sibling::*/child::*[@id=$menuId] | 
           following-sibling::*/child::*[@id=$menuId]"> 
    <xsl:copy> 
      <xsl:copy-of select="@*"/> 
     <xsl:apply-templates select="item"/> 
    </xsl:copy> 
    </xsl:if> 
</xsl:template> 


</xsl:stylesheet> 

난 그냥 특정 노드를 얻기 위해 몇 가지 규칙을 적용하고있다. 괜찮아. 하지만 지금은 선택한 메뉴에서 X (이 숫자는 다를 수 있음) 레벨을 가져와야합니다.

예를 들어. 는 X 레벨 번호가 2이고 menuId와이 1.1.2.3 인 경우 결과는 다음과 같습니다

<menu> 
    <item id=1.1> 
     <item id=1.1.1> 
     <item id=1.1.1.1> 
     <item id=1.1.1.2> 
     <item id=1.1.1.3> 
     </item> 
    </item> 
    <item id=1.2> 
    </item> 
</menu> 

는 X 레벨 번호가 1 인 경우

는, 결과는 다음과 같습니다

<menu> 
     <item id=1.1.1> 
     <item id=1.1.1.1> 
     <item id=1.1.1.2> 
     <item id=1.1.1.3> 
     </item> 
</menu> 

현재를 얻으려면 레벨 count(ancestor::*)을 사용합니다. 하지만 노드 [@id = $ menuId] 레벨을 얻는 방법을 모르겠습니다. 내 IF에 count(ancestor::*) >= (count(ancestor::node[@id = $menuId]) - X)과 같은 내용을 포함해야합니다.

감사합니다. 이 접근하는 내가 생각할 수있는

답변

0

가장 효율적인 방법은 apply-templates 체인 아래로 계산 매개 변수를 전달하는 것입니다 :

<xsl:variable name="targetDepth" select="count(//item[@id=$menuId]/ancestor::item)" /> 
<!-- I haven't thought this through in great detail, it might need a +1 --> 

<xsl:template match="item"> 
    <xsl:param name="depth" select="0" /> 
    .... 
    <xsl:if test=".... and ($targetDepth - $depth) &lt;= $numLevels"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates select="item"> 
     <xsl:with-param name="depth" select="$depth + 1" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:if> 
</xsl:template> 
+0

감사 @Ian. 나를 위해 빠진 것은 targetDepth였다. 그것은 내가 필요한 것입니다. 미안하지만 투표 할 수는 없어. :) – Adriano

+0

@Adriano는 아이템 ID가 유일해야한다는 것을 알아 두십시오 - 동일한 ID를 가진 두 개의 다른 item 아이템이 있다면'targetDepth'는 각각의 깊이의 _sum_가 될 것입니다. –

+0

나는 그것을 안다. 나는 이것에 관해 완전히 알고 있고 이미 그것이 유일해야한다는 것을 내 팀에 말했습니다. 감사. – Adriano