XSLTなんて久しぶりに書いた
2ちゃんを徘徊していたら、たまたまこんなの見つけた。
XML+XSLTでインライン要素ってどうやって実現するの? 例えば、 <top> <block> テキスト<link url="http://example.jp">リンク</link> </block> </top> というXMLがあったときにXSLT側はどうすれば <p> テキスト<a href="http://example.jp">リンク</a> </p> のようにできるの? <top> <block> <text>テキスト</text><link url="http://example.jp">リンク</link> </block> </top> とは書きたくないんだけど。XML使いのスレ2.0
うは、昔の自分を見てるようだw
確か3年の頃だったか、同じような問題にはまっていた。
XSLTなんてそれ以来だけど、適当に書いてみた。
まず、対象となるXMLはこんな感じ。
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet href="style.xsl" type="text/xsl"?> <page title="test"> <link url="http://www.google.co.jp">リンク</link>とか、 画像<img url="http://hogehost/image/image.png" alt="hoge" w="80" h="15"/>とか、 バナーとか<banner base="http://hogehost/" img="image/image.png" link="index.html" alt="hoge" w="80" h="15"/>、<br/> 改行とか、<strong>強調</strong>とか。 </page>
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> <xsl:template match="page"> <html> <head> <title><xsl:value-of select="@title"/></title> </head> <body><p> <xsl:call-template name="body"/> </p></body> </html> </xsl:template> <!-- ページ本体部分のテンプレート --> <xsl:template name="body"> <!-- 子要素の名前によって適用するテンプレートを分岐 --> <xsl:for-each select="node()"> <xsl:choose> <xsl:when test="name(.)='link'"> <xsl:call-template name="link"/> </xsl:when> <xsl:when test="name(.)='img'"> <xsl:call-template name="img"/> </xsl:when> <xsl:when test="name(.)='banner'"> <xsl:call-template name="banner"/> </xsl:when> <xsl:when test="name(.)='strong'"> <xsl:call-template name="strong"/> </xsl:when> <xsl:when test="name(.)='br'"> <br/> </xsl:when> <xsl:otherwise> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <!-- ハイパーリンクのテンプレート --> <xsl:template name="link"> <a> <xsl:attribute name="href"> <xsl:value-of select="@url"/> </xsl:attribute> <xsl:value-of select="."/> </a> </xsl:template> <!-- 画像のテンプレート --> <xsl:template name="img"> <img> <xsl:attribute name="src"> <xsl:value-of select="@url"/> </xsl:attribute> <xsl:attribute name="alt"> <xsl:value-of select="@alt"/> </xsl:attribute> <xsl:attribute name="width"> <xsl:value-of select="@w"/> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of select="@h"/> </xsl:attribute> </img> </xsl:template> <!-- バナー(リンク+画像)のテンプレート --> <xsl:template name="banner"> <a> <xsl:attribute name="href"> <xsl:value-of select="@base"/><xsl:value-of select="@link"/> </xsl:attribute> <img> <xsl:attribute name="src"> <xsl:value-of select="@base"/><xsl:value-of select="@img"/> </xsl:attribute> <xsl:attribute name="alt"> <xsl:value-of select="@alt"/> </xsl:attribute> <xsl:attribute name="width"> <xsl:value-of select="@w"/> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of select="@h"/> </xsl:attribute> </img> </a> </xsl:template> <!-- テキストを強調表示する部分のテンプレート --> <xsl:template name="strong"> <strong> <xsl:value-of select="."/> </strong> </xsl:template> </xsl:stylesheet>
<html> <head> <title>test</title> </head> <body><p> <a href="http://www.google.co.jp">リンク</a>とか、 画像<img src="http://hogehost/image/image.png" alt="hoge" width="80" height="15"/>、 バナーとか<a href="http://hogehost/index.html"> <img src="http://hogehost/image/image.png" alt="hoge" width="80" height="15"/> </a>、<br/> 改行とか、<strong>強調</strong>とか。 </p></body> </html>
いろいろと手抜きだけど、一応動く。
肝心な部分は、bodyテンプレートで、node関数使って子要素を全部取得、その一つ一つの要素に適用すべきテンプレートを選んでいる。
このテンプレートはmatch属性じゃなくてname属性を使ってるから、page要素以外にブロック要素を作ったとしても、そこから呼び出せば動く・・・はず。
XSLTも面白くはあるんだけど、なんと言うか、間抜けだよね。がんばってXSLT書いたところで独自規格でしか無いわけだし。
この質問者はここから更にDTDやらXML Schemaやらやりだすと予言w