【问题标题】:xsl ancestor-or-self not return resultxsl 祖先或自我不返回结果
【发布时间】:2013-05-14 15:05:30
【问题描述】:

我在尝试为每个节点的每个父节点时遇到问题。我有这样的 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="*"/>

如果可以的话,请帮帮我。

统一更新:
我想要一些像菜单一样的东西(如果选择了 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>

【问题讨论】:

  • 你的问题不是特别清楚,更像是一个陈述而不是一个问题。您能否更具体一点...特别是,您正在寻找什么作为输出。
  • 调用render模板时的当前节点是什么?您能否向我们展示更多您的 XSLT?

标签: xslt ancestor


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    所以本质上你想要生成一个树结构,其中所有节点都“折叠”,除了具有指定 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 有一个 &lt;menu&gt; 根元素包裹在顶级 item 元素集周围,如果不是这种情况,您将不得不适当地调整匹配并选择表达式)。

    如果您还想显示目标 id 下方的级别(例如,当目标 id 为 122 时包括 6、9 层),那么只需更改

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

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

    【讨论】:

      【解决方案3】:

      看看下面的解决方案

      <?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>
      

      【讨论】:

        猜你喜欢
        • 2012-04-23
        • 1970-01-01
        • 2017-11-25
        • 2023-03-03
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多