Как найти уровень определенного узла

Мой 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 (это число может варьироваться) выше уровней из выбранного menuId

Например. Если номер уровня 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]. Мне нужно включить что-то вроде count(ancestor::*) >= (count(ancestor::node[@id = $menuId]) - X) внутри моего ЕСЛИ

Благодарю.

1 ответ

Решение

Я думаю, что наиболее эффективный способ приблизиться к этому - передать параметр подсчета вниз по 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>
Другие вопросы по тегам