下記のようなXMLがあります。


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

<document>
<id>a</id>
<text>あああ</text>
<id>b</id>
<text>いいい</text>
<id>c</id>
<text>ううう</text>
<id>d</id>
<id>e</id>
<text>えええ</text>
<id>f</id>
<text>おおお</text>
</document>
---------------------------------------------------

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

---------------------------------------------------
<HTML>
<BODY>
<TABLE border="1">
<TR>
<TD>a:あああ</TD>
<TD>b:いいい</TD>
</TR>
<TR>
<TD>c:ううう</TD>
<TD>e:えええ</TD>
</TR>
<TR>
<TD>f:おおお</TD>
<TD>&nbsp;</TD>
</TR>
</TABLE>
</BODY>
</HTML>
---------------------------------------------------

条件、
・idの総数は未知です。
・id"d"のように、<text>要素がない場合はセル自体をつめて表示します。もちろんidも表示しません。
・表示すべき要素が奇数個であった場合は、最後に空白セルを追加します。

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

回答の条件
  • 1人2回まで
  • 登録:2006/11/08 14:03:11
  • 終了:2006/11/15 14:05:02

回答(2件)

id:lains_you No.1

lains_you回答回数50ベストアンサー獲得回数102006/11/08 15:56:30

ポイント35pt

 力技で変換してみました。IE7で動作確認。

<?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"/>

<!-- ID群変数 -->
<xsl:variable name="ids" select="//id[name(./following-sibling::*[position()=1]) = 'text']"/>


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

		<table border="1">
			<xsl:if test="count($ids) &gt; 0">
				<xsl:call-template name="list">
					<xsl:with-param name="no">1</xsl:with-param>
					<xsl:with-param name="count" select="count($ids)"/>
				</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="id1" select="$ids[position() = $no]"/>
	<xsl:variable name="id2" select="$ids[position() = $no + 1]"/>

	<tr>
		<xsl:call-template name="item">
			<xsl:with-param name="id" select="$id1"/>
			<xsl:with-param name="text" select="$id1/following-sibling::*[position()=1]"/>
		</xsl:call-template>
		
		<xsl:choose>
			<xsl:when test="$no &lt; $count">
				<xsl:call-template name="item">
					<xsl:with-param name="id" select="$id2"/>
					<xsl:with-param name="text" select="$id2/following-sibling::*[position()=1]"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<!-- 対象IDなし -->
				<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>
id:kuroda

ありがとうございます!

動作確認したところ、確かに要求どおりに動いているようです。

これからじっくりソースを読んでみます。

2006/11/11 09:38:19
id:chaobun No.2

chaobun回答回数38ベストアンサー獲得回数62006/11/08 19:34:16

ポイント35pt

tokuya_n さんのおっしゃる通り、XMLの構造がやりたいことにかなっていないと思われます。

XMLは、各タグの書かれている順番や位置、数などを気にせずに記述できる半構造データというツリー構造を持っています。

現在のデータ構造はイメージとしては

           <document>

              |

   ------------- ~ ----------------------- ~

  |  |  |      |   |   |   |

 <id> <id> <id>   <text> <text> <text> <text>

  |  |  |      |   |   |   |

  a  b  c     あああ いいい ううう えええ

ですね。(文字の幅の問題できれいに出来ませんでした…読みにくくてすみません)

この構造ではidがdであるときのテキスト要素があるかないかの判別が出来ません(つまり<document>内で<id>タグのn番目、<text>タグのm番目といった指定の仕方でアクセスをすることは出来ますが、イメージ的には上述したようなツリー構造になるので、<id>タグと<text>タグを交互に記述しても、XMLではそれは無視されてしまうからです)。


おっしゃることをしたいのであれば、tokuya_nさんの提案されている用に、組になるタグを、例えば<word></word>で囲ってやることによってaとあああが対であることをコンピュータが読むことが出来るようになります。

           <document>

             |

     ---------------------- ~

    |        |

   <word>     <word>  ~

    |        |

  ----------    ---------

 |      |   |     |

<id>   <text> <id>   <text>

 |      |   |     |

 a     あああ  i    いいい


この場合処理としては

1 for-each によってそれぞれのword要素を順番に呼び出し、

2 count()を使ってtextタグの有無を判定して<text>か空白を書き込むように選択

3 for-eachを抜ける

4 count()でwordの個数を判定して奇数の場合に空白セルを挿入

というようにすれば、簡単に実装できると思います。

もし、それがフォーマットを変えるのが不可能であれば、XMLを使わずにJavaスクリプトなどでがりがり一行ずつの判定をしなければならない気がします…そうするとXMLで書いてある意味が全くありませんし、厳密に改行や、タグの順番が要求されてきますが。

id:kuroda

丁寧なご説明ありがとうございます。

また、返事が遅くなりすみません。

(こんなに早く適切なご回答が得られると思っていませんでした!)


tokuya_n さんにもご指摘いただいたように、XMLは

<document>

<word>

<id>a</id>

<text>あああ</text>

</word>

<word>

<id>b</id>

<text>いいい</text>

</word>

</document>

のような形で結構です。

ただ、後半部分で教えていただいたような方法では、表の途中に空白の欄ができてしまうと思うのですが、

これは詰めて表示したいと思います。

ところで、はてな初心者で恐縮ですが、このような場合(質問の条件を変えてしまったので)新しく質問を立て直したほうがよいでしょうか

2006/11/11 09:24:00
  • id:tokuya_n
    XMLファイルのフォーマットは変更不可ですか?

    ---

    <document>
    <id>a</id>
    <text>あああ</text>
    <id>b</id>
    <text>いいい</text>
    ...
    </document>

    ---

    というのはちょっと変です。
    せめて

    <document>
    <word>
    <id>a</id>
    <text>あああ</text>
    </word>
    <word>
    <id>b</id>
    <text>いいい</text>
    </word>
    </document>

    とかならわかりますが
  • id:kuroda
    返事が遅くなりすみません。

    XMLはご指摘の形

    <document>
    <word>
    <id>a</id>
    <text>あああ</text>
    </word>
    <word>
    <id>b</id>
    <text>いいい</text>
    </word>
    </document>

    でも結構です。
  • id:chaobun
    lains_you さんの回答で問題が解決しているのであれば、僕は完全に勘違いをしていたようなので、ポイントつけないで下さい…。僕もはてなは超初心者(これ多分初めてか2回目くらいの回答)なので、色々勘違いしてました…今後気をつけようと思います。本当にごめんなさい、大変失礼しましたm(__)m
  • id:kuroda
    すみません、みなさんに教えてもらった内容は完璧だったのに、
    設問に問題がありました。

    新たな質問をこちら↓に立てています。
    http://q.hatena.ne.jp/1164170204

    ご協力いただければうれしいです。

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

トラックバック

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

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

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません