2012-05-02 33 views
7

私はchaptersというXML文書を持ち、sectionsをネストしています。 私は、どのセクションでも、最初の第2レベルの祖先を見つけることを試みています。 これはancestor-or-self軸の最後から2番目のセクションです。 擬似コード:xpathを持つ最後から2番目のノードを見つけよう

<chapter><title>mychapter</title> 
    <section><title>first</title> 
    <section><title>second</title> 
     <more/><stuff/> 
    </section> 
    </section> 
</chapter> 

私の選択:もちろん

<xsl:apply-templates 
    select="ancestor-or-self::section[last()-1]" mode="title.markup" /> 

まで動作し、最後の() - 1が定義されていない(現在のノードがfirst部です)。

現在のノードがsecondセクションの下にある場合、タイトルはsecondです。 それ以外の場合は、タイトルがfirstになります。

+0

DocBookを使用するためのUpvote。 –

答えて

4

これであなたのXPathを交換してください:あなたはすでに1を除くすべてのケースで右ノードを見つけることができますので

ancestor-or-self::section[position()=last()-1 or count(ancestor::section)=0][1] 

、私もにあなたのXPathを更新firstセクション(or count(ancestor::section)=0)を見つけ、その後、選択し最初の一致(ancestor-or-self軸を使用しているので、ドキュメントの逆順で)を返します([1])。

(ancestor-or-self::section[position() > last() -2])[last()] 

これはsectionという名前の、おそらく最初の二つの最上位の祖先の最後の選択:

+0

それは動作します - ありがとう。あなたのソリューションを試した後、私はこれで簡単にするかもしれないと思ったが、残念ながら、常に現在のセクションを選択しているようだ。 '' ancestor-or-self :: section [last() - boolean(ancestor :: section)] '' ancestor-or-self :: section:[last()-1またはlast()] [1] ' – Tim

+0

@Tim' ] [1] ' –

+0

@アレ、エレガントなソリューション! – Tim

2

はここより短く、より効率的なソリューションです。そのような祖先が1つしかない場合は、それ自体が最後です。

<chapter> 
    <title>mychapter</title> 
    <section> 
     <title>first</title> 
     <section> 
      <title>second</title> 
      <more/> 
      <stuff/> 
     <section> 
      <title>third</title> 
     </section> 
     </section> 
    </section> 
</chapter> 
:この変換は、以下の文書(提供さに基づいて、より多くのネストされた section要素を追加)に印加さ​​れると

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="section"> 
    <xsl:value-of select="title"/> 
    <xsl:text> --> </xsl:text> 

    <xsl:value-of select= 
    "(ancestor-or-self::section[position() > last() -2])[last()]/title"/> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="text()"/> 
</xsl:stylesheet> 

:ここ

は完全変換あります

正しい結果が得られます

first --> first 
second --> second 
third --> second 
関連する問題