ルーベンス・ファリアスの回答に対するコメントから(実際には、質問を編集して含める必要があります)、隣接するBulletText
要素のグループをリストに変換する一般的な方法が必要なようです。これにより、次の 2 つの質問にたどり着きます。そのようなグループをどのように見つけるか、そしてそれらを見つけた後、それらをどのようにリストに変換するかです。
BulletText
グループを見つけるには、直前の兄弟が要素ではないすべての要素を探す必要がありますBulletText
。それらのそれぞれがグループを開始し、それらはリストに変換しようとしている要素です。したがって、最初にやりたいことは、それらを見つける XPath 式を作成することです。
BulletText[not(preceding-sibling::*[1][name()='BulletText'])]
その XPath 式の述語を見ると、必要なことはまさに私が言ったことです。つまり、最初に先行する兄弟 ( ) の名前が ではBulletText
ない場合、要素に一致します。要素に先行する兄弟がない場合でも、この式はそれに一致することに注意してください。preceding-sibling::*[1]
BulletText
これで、これらのグループの開始要素に一致するテンプレートを作成できます。このテンプレートには何を入れますか? これらの要素を要素に変換するLIST
ので、テンプレートは次のようになります。
<LIST>
...
</LIST>
簡単です。しかし、そのリストに入力する要素をどのように見つけるのでしょうか? 対処しなければならないケースが 2 つあります。
1 つ目は単純です。次のすべての兄弟がBulletText
要素である場合、この要素とそれに続くすべての兄弟をリストに入力します。
2番目は難しいです。要素ではない次の兄弟がある場合BulletText
、リストを現在の要素の親のすべての子にする必要があります。現在の要素から始まり、停止要素の前で終わります。count()
これは、開始インデックスと終了インデックスを計算する関数と、position()
各要素の位置を見つける関数を使用する必要がある場合です。
完成したテンプレートは次のようになります。
<xsl:template match="BulletText[not(preceding-sibling::*[1][name()='BulletText'])]">
<!-- find the element that we want to stop at -->
<xsl:variable name="stop" select="./following-sibling::*[name() != 'BulletText'][1]"/>
<LIST>
<xsl:choose>
<!-- first, the simple case: there's no element we have to stop at -->
<xsl:when test="not($stop)">
<xsl:apply-templates select="." mode="item"/>
<xsl:apply-templates select="./following-sibling::BulletText" mode="item"/>
</xsl:when>
<!-- transform all elements between the start and stop index into items -->
<xsl:otherwise>
<xsl:variable name="start_index" select="count(preceding-sibling::*) + 1"/>
<xsl:variable name="stop_index" select="count($stop/preceding-sibling::*)"/>
<xsl:apply-templates select="../*[position() >= $start_index
and position() <= $stop_index]"
mode="item"/>
</xsl:otherwise>
</xsl:choose>
</LIST>
</xsl:template>
他に 2 つのテンプレートが必要です。BulletText
1 つは要素を項目に変換します。ここでは、現在使用しているテンプレートを呼び出さずmode
に要素に適用できるように使用します。BulletText
<xsl:template match="BulletText" mode="item">
<ITEM>
<xsl:value-of select="."/>
</ITEM>
</xsl:template>
次に、最初のテンプレートが出力を生成することから一致しないBulletText
要素を保持するテンプレートも必要です (恒等変換を使用している場合、それらは単にコピーされるためです)。
<xsl:template match='BulletText'/>
XSLT のテンプレート優先ルールの魔法により、BulletText
両方のテンプレートが一致する要素は最初のテンプレートによって変換され、残りはこのテンプレートによってキャッチされます。
これら 3 つのテンプレートを恒等変換に追加するだけで、準備完了です。