尝试每个节点的每个父节点时都有问题。我有这样的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>
答案 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>