前回、

http://q.hatena.ne.jp/1162962189
でXMLに関し質問させていただいた者です。

いただいた回答は完璧だったのですが、設問の条件が少し変わりました。

下記のXMLのように、<text>タグの前に別のタグ(ここでは<name>)があるケースがあり、"position()=1"のような指定ができないケースがあります。

-------------------------
<?xml version="1.0" ?>

<document>
<title>
<id>a</id>
<text>あああ</text>
</title>
<title>
<id>b</id>
<text>いいい</text>
</title>
<title>
<id>c</id>
<name>たろう</name>
<text>ううう</text>
</title>
<title>
<id>d</id>
</title>
<title>
<id>e</id>
<text>えええ</text>
</title>
<title>
<id>f</id>
<name>はなこ</name>
<text>おおお</text>
</title>
</document>
-------------------------

このXMLから下記のようなidとtextを併記したHTMLを生成するXSLを作りたいと思います。

出力したいHTMLの形式と条件は前回とまったく同じです。

※文字数の制限で書ききれませんでした。
http://q.hatena.ne.jp/1162962189
の質問を見ていただけますでしょうか。

再度、皆さんのお知恵を貸していただければうれしいです。

よろしくお願いします。

回答の条件
  • 1人10回まで
  • 登録:
  • 終了:2006/11/26 13:09:05
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:lains_you No.1

回答回数50ベストアンサー獲得回数10

ポイント80pt
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="shift_jis" indent="yes"/>

<!-- title要素変数 -->
<xsl:variable name="titles" select="//title[count(./id) != 0 and count(./text) != 0]"/>


<!-- ルート -->
<xsl:template match="/document">
	<html>
	<body>

		<table border="1">
			<xsl:if test="count($titles) &gt; 0">
				<xsl:call-template name="list">
					<xsl:with-param name="no">1</xsl:with-param>
					<xsl:with-param name="count" select="count($titles)"/>
				</xsl:call-template>
			</xsl:if>
		</table>
		
	</body>
	</html>
</xsl:template>


<!-- リスト -->
<xsl:template name="list">
	<xsl:param name="no"/>
	<xsl:param name="count"/>
	<xsl:variable name="title1" select="$titles[position() = $no]"/>
	<xsl:variable name="title2" select="$titles[position() = $no + 1]"/>

	<tr>
		<xsl:call-template name="item">
			<xsl:with-param name="id" select="$title1/id"/>
			<xsl:with-param name="text" select="$title1/text"/>
		</xsl:call-template>
		
		<xsl:choose>
			<xsl:when test="$no &lt; $count">
				<xsl:call-template name="item">
					<xsl:with-param name="id" select="$title2/id"/>
					<xsl:with-param name="text" select="$title2/text"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<td> </td>
			</xsl:otherwise>
		</xsl:choose>
	</tr>
	
	<xsl:if test="$no + 1 &lt; $count">
		<xsl:call-template name="list">
			<xsl:with-param name="no" select="$no + 2"/>
			<xsl:with-param name="count" select="$count"/>
		</xsl:call-template>
	</xsl:if>
</xsl:template>


<!-- TD内容 -->
<xsl:template name="item">
	<xsl:param name="id"/>
	<xsl:param name="text"/>
	
	<td>
		<xsl:value-of select="$id"/>
		<xsl:text>:</xsl:text>
		<xsl:value-of select="$text"/>
	</td>
</xsl:template>
</xsl:stylesheet>

 ほぼ前回からの流用です。

 select="//title[count(./id) != 0 and count(./text) != 0]"でid要素とtext要素を子要素として持つtitle要素のみを抽出しています。

 上記の条件ではidやtextの値が空であっても良いようにしてありますが、空値以外のものを検索する場合はselect="//title[./id != '' and ./text != '']"などに修正してください。

 IE7で動作確認。

id:kuroda

lains_youさん、たびたびのご教示ありがとうございます。

なるほど、発想の転換でいろいろな条件が作れるんですね。

本当に助かりました!

2006/11/26 13:06:05
  • id:golgachov
    いまさら遅いですけど参考までに、以下でできます(MSXSL 4.0)
    <xsl:template match="/">
    <HTML><BODY>
    <TABLE>
    <xsl:apply-templates select="//text"/>
    </TABLE>
    </BODY></HTML>
    </xsl:template>

    <xsl:template match="text">
    <!-- text要素リスト中の奇数番目なら TR開始-->
    <xsl:if test="position() mod 2 = 1">
    <xsl:text disable-output-escaping="yes">&lt;TR></xsl:text>
    </xsl:if>
    <!-- 各text要素について -->
    <TD>
    <!--id要素のうちで このtext要素のすぐ前にあるものの値 -->
    <xsl:value-of select="preceding-sibling::id[1]" />
    <xsl:text>:</xsl:text>
    <xsl:value-of select="."/>
    </TD>
    <!-- TEXT要素リスト中の奇数番目かつ末尾要素なら 空のTDとTR終了-->
    <xsl:if test="position()=last() and position() mod 2 = 1">
    <TD></TD>
    <xsl:text disable-output-escaping="yes">&lt;/TR></xsl:text>
    </xsl:if>
    <!-- text要素リスト中の偶数番目なら TR終了 -->
    <xsl:if test="position() mod 2 = 0">
    <xsl:text disable-output-escaping="yes">&lt;/TR></xsl:text>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません