xsl ancestor-or-self不返回结果

时间:2013-05-14 15:05:30

标签: xslt ancestor

尝试每个节点的每个父节点时都有问题。我有这样的XML:

<item name="news" id="77">
  <items>
    <item id="102" />
    <item id="103" />        
  </items>
</item>    
<item id="86">
  <items>
    <item id="122">
      <items>
        <item id="6" />
        <item id="9" />
      </items>
    </item>
    <item id="12">
      <items>
        <item id="13" />
        <item id="18" />
        <item id="19" />
      </items>
    </item>
  </items>
</item>
<item name="sitemap" id="88" />       

在模板中我尝试这样:

<xsl:template name="render">
<xsl:param name="length" />
<xsl:param name="item" />
  <xsl:for-each select="ancestor-or-self::item[@id='9']">        
    some code
  </xsl:for-each>      
<xsl:apply-templates select="*"/>

如果可以,请帮帮我。

UPD:
我想得到一些像菜单(如果选择id = 9的选项):

<ul>
 <li>77</li>
 <li>
  86
  <ul>
   <li>
    122
    <ul>
     <li>6</li>
     <li>9</li>
    </ul>
   </li>
   <li>12</li>
  </ul>
 </li>
 <li>88</li>
</ul>

我的XSLT(我想到了)并不好:

<xsl:template match="/">
<ul>
<xsl:call-template name="render">
  <xsl:with-param name="item" select="item[@id='9']" />
  <xsl:with-param name="length" select="0" />
</xsl:call-template>
</ul>
</xsl:template>

<xsl:template name="render">
  <xsl:param name="length" />
  <xsl:param name="item" />
  <xsl:for-each select="$item/ancestor-or-self::item[@id='9']">        
    <xsl:if test="position()=length">
      <xsl:variable name="current" select="." />
      <xsl:for-each select="../item">
        <xsl:choose>
          <xsl:when test=".=current">
            <li class="selectedItem">
              <p>
                <xsl:value-of select="@id"/>
              </p>
              <xsl:call-template name="render">
                <xsl:with-param name="length" select="$lenght + 1" />
                <xsl:with-param name="item" select="$item" />
              </xsl:call-template>
            </li>
          </xsl:when>
          <xsl:otherwise>
            <li>
              <p>
                <xsl:value-of select="@id"/>
              </p>
            </li>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
    </xsl:if>
  </xsl:for-each>      
<xsl:apply-templates select="*"/>
</xsl:template>

3 个答案:

答案 0 :(得分:1)

您还没有明确问题,但我想知道您是否正在寻找参数node $ item的祖先,而不是上下文节点的祖先?如果是这样,那将是

select="$item/ancestor-or-self::item[@id='9']

但是,在你的示例XML中,@ id ='9'的唯一节点不是任何东西的祖先,所以我怀疑我在黑暗中摸索。

答案 1 :(得分:1)

所以基本上你想要生成一个树结构,其中所有节点都是&#34;折叠&#34;除了具有指定id的那个。我会采用不同的方法:

<xsl:template match="items | menu" mode="menu">
  <xsl:param name="targetId" />
  <ul>
    <xsl:apply-templates select="item" mode="menu">
      <xsl:with-param name="targetId" select="$targetId"/>
    </xsl:apply-templates>
  </ul>
</xsl:template>

<xsl:template match="item" mode="menu">
  <xsl:param name="targetId" />
  <li>
    <xsl:if test="@id = $targetId">
      <xsl:attribute name="class">selectedItem</xsl:attribute>
    </xsl:if>
    <xsl:value-of select="@id"/>

    <!-- expand the branch only if it contains the target id -->
    <xsl:apply-templates select="items[.//@id = $targetId]" mode="menu">
      <xsl:with-param name="targetId" select="$targetId"/>
    </xsl:apply-templates>
  </li>
</xsl:template>

当您想要为特定ID呈现菜单时,您只需说出

<xsl:apply-templates select="/menu" mode="menu">
  <xsl:with-param name="targetId" select="'9'"/>
</xsl:apply-templates>

(这里我假设您的原始XML有一个<menu>根元素包含在item个元素的顶级集合中,如果情况并非如此,那么您可以使用 <xsl:apply-templates select="items[.//@id = $targetId]" mode="menu"> 元素。{我必须调整匹配并适当选择表达式。

如果您还要显示低于目标ID的级别(例如,当目标ID为122时包括6,9层),则只需更改

    <xsl:apply-templates select="items[current()//@id = $targetId]" mode="menu">

{{1}}

答案 2 :(得分:0)

查看以下解决方案

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="home" select="//item[@name='home']" />


<xsl:variable name="current_item" select="//item[@id = '55']" />

<xsl:variable name="parents_line" select="$current_item/ancestor-or-self::item" />

<xsl:variable name="path">
<xsl:for-each select="$parents_line">
   <xsl:text>/</xsl:text>
   <xsl:value-of select="@id"/>
   <xsl:if test="position()=last()">/</xsl:if>
</xsl:for-each>

</xsl:variable> 

<xsl:template match="*">
  <xsl:call-template name="menu" />
</xsl:template>

<xsl:template name="menu">
    <xsl:param name="level" select="1" />
    <xsl:param name="start" select="$home" />

    <ul>
      <xsl:for-each select="$start/items/item">
       <xsl:variable name="current_id" select="@id" />
        <li>
          <xsl:value-of select="@name" />

          <xsl:if test="contains($path, concat('/', $current_id, '/') )">
            <xsl:call-template name="menu">
              <xsl:with-param name="level" select="$level+1" />
              <xsl:with-param name="start" select="." />
            </xsl:call-template>
          </xsl:if>
        </li>
      </xsl:for-each>
    </ul>
  </xsl:template>

</xsl:stylesheet>