www-html@w3.org from January 2003: XHTML 2.0 considered harmful (英語)の一連の議論で、br要素が如何に「便利」であるかを熱弁している人がいるのですが、この糞要素のお陰でHTMLという言語は勘違いされるのでありますよ。
より良い言語を作るのに、人間様が過去の古い計算機の都合に合わせてどうするのですか。backwards compatibility
が大事なら、あまり良くない言語を使い続ければ宜しいでしょう。私も当分そうするつもりです。何故足を引っ張る必要がありますか。本気で理解不可能です。
というわけで(どういうわけで?)、br要素で区切られたノードリストを、XHTML 2.0のl要素(line要素)としてグループ化するXSLTテンプレートを考案してみました。XHTML 2.0は草案ですし名前空間もどうなるか分からないので、とりあえず名前空間は無いものとして扱います。ソース文書の方も名前空間無しってことで。
これは例えば、hr要素か何かで区切られたノードリストをdiv要素か何かとしてグループ化する際にも応用できる と 思います ?
<xsl:template name="brでl要素に分割するテンプレ">
<xsl:for-each select="child::br[position() = 1]">
<l>
<xsl:for-each select="preceding-sibling::node()">
<xsl:apply-templates select="self::node()" />
</xsl:for-each>
</l>
</xsl:for-each>
<xsl:for-each select="child::br">
<l>
<xsl:if test="position() = last()">
<xsl:for-each select="following-sibling::node()">
<xsl:apply-templates select="self::node()" />
</xsl:for-each>
</xsl:if>
<xsl:variable name="posBR">
<xsl:for-each select="following-sibling::br[position() = 1]">
<xsl:number level="single" count="node()" />
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="following-sibling::node()">
<xsl:variable name="posNode">
<xsl:number level="single" count="node()" />
</xsl:variable>
<xsl:if test="name() != 'br' and $posNode < $posBR">
<xsl:apply-templates select="self::node()" />
</xsl:if>
</xsl:for-each>
</l>
</xsl:for-each>
</xsl:template>
主にp要素にマッチするテンプレート内でこのように呼び出します。
<xsl:template match="p">
<p>
<xsl:apply-templates select="attribute::*" />
<xsl:choose>
<xsl:when test="boolean(child::br) = true()">
<xsl:call-template name="brでl要素に分割するテンプレ" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="child::node()" />
</xsl:otherwise>
</xsl:choose>
</p>
</xsl:template>
XML的に腐ったデータを再生するには、冗長なXSLT文書を書かなくてはならないと言うことでしょうか。一方DOMインターフェイスを使えばこのような変換方法の考案はサクサクですね(謎)。XSLT(1.0)やXPath(1.0)はまだ非力ですから、文章を書くようにDOMを使いこなせるなら(謎)、無理して勉強する必要も無いと思います。
というか、スタイルシートが整形過程であるとするなら、DOMインターフェイスを使った変換だって立派な「スタイルシート」です。コードはアホみたいに膨らむし処理は遅めかもしれませんが、こっちの方が痒いところに手が届きます。もう比較にならないくらい圧倒的。SAXってどうなんだろう。
先程のサンプルではロケーションパスと式(Expression)について省略せずに書いていますが、頻繁にXSLTを弄る機会を持てない方にはお勧めの書き方です。常にデータ型とカレントノードを意識して書くことが出来るからです。