- PR -

XSLTでXMLの構造を変更する

1
投稿者投稿内容
koko
会議室デビュー日: 2004/04/22
投稿数: 3
投稿日時: 2004-09-30 15:32
皆様こんにちは。
koko と申します。

ただいま、XSLTでXMLの構造を変更しようとしているのですが、
壁にぶつかってしまっています。
よろしければ、お助け願えないでしょうか?

<やりたいこと>
AccessからそのままXMLで書き出したようなXMLを
ちゃんとした表構造にしたいのです。
次のようなXMLがあります。(宣言は省略します。)

<Documents>
<data>
<name>A</name>
<price>1000</price>
</data>
<data>
<name>B</name>
<price>100</price>
</data>
<data>
<name>A</name>
<price>2000</price>
</data>
<data>
<name>B</name>
<price>200</price>
</data>
<data>
<name>B</name>
<price>300</price>
</data>
<data>
<name>A</name>
<price>3000</price>
</data>
</Documents>

これを、<name> 要素ごとで分けたTableにしたいのです。

<Documents>
<table>
<Row>
<name>A</name>
<price>1000</price>
</Row>
<Row>
<name>A</name>
<price>2000</price>
</Row>
<Row>
<name>A</name>
<price>3000</price>
</Row>
</table>
<table>
<Row>
<name>B</name>
<price>100</price>
</Row>
<Row>
<name>B</name>
<price>200</price>
</Row>
<Row>
<name>B</name>
<price>300</price>
</Row>
</table>
</Documents>

<name>要素でソートした後、
preceding-sibling で前の要素の内容を比較して
行けば良いと思っていたのですが、
<name>要素が変わった時点で、</Table> タグで
閉じなければなりませんが、その方法が良くわかりません。
何卒、宜しくお願い申し上げます。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-09-30 15:53
http://qa.xml.gr.jp/data/xsl/index.xml

要素の集約(2) あたり、その他の方法もあります。

XSLT2.0 では
はるかに簡単です、SAXON8 などを利用しましょう。

http://dac.lolipop.jp/trans/nono.html

グループ化とか で検索したほうが早いかも
るぱん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 1370
投稿日時: 2004-09-30 16:23
るぱんです。

下記コードの中身をそのま貼り付けて試してみてください。
(多分折り返してたりすると思いますので、その辺は調整してくださいね。)
お気に召しますでしょうか?
XML文書のXSL参照パス指定欄の変更も忘れずに。

コード:

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:element name="HTML">
<xsl:element name="HEAD">
</xsl:element>
<xsl:element name="BODY">
<xsl:element name="TABLE">
<xsl:attribute name="border">1</xsl:attribute>
<xsl:for-each select="./Documents/data">
<xsl:sort select="./name/text()"/>
<xsl:sort select="./price/text()"/>
<xsl:element name="TR">
<xsl:element name="TD">
<xsl:value-of select="./name/text()"/>
</xsl:element>
<xsl:element name="TD">
<xsl:value-of select="./price/text()"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>



[編集]
追記:
DB系の出身と勝手に推測してるんですが、
表の内部を<ROW>とか書いてると、HTMLやってる人たちに馬鹿にされちゃいますよ。

HTMLの表はテーブルタグ(table)でtdとtrで行と列を表します。
HTMLも勉強してくださいね。
[/編集]

[ メッセージ編集済み 編集者: るぱん 編集日時 2004-09-30 16:35 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-09-30 16:42
引用:

るぱんさんの書き込み (2004-09-30 16:23) より:
追記:
DB系の出身と勝手に推測してるんですが、
表の内部を<ROW>とか書いてると、HTMLやってる人たちに馬鹿にされちゃいますよ。

HTMLの表はテーブルタグ(table)でtdとtrで行と列を表します。
HTMLも勉強してくださいね。


HTMLの表とはどこにも書いてないと思いますが。表の「行」をROWと表現するのは問題ないで
しょう。
るぱん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 1370
投稿日時: 2004-09-30 16:50
るぱんです。

失礼いたしました。
[編集]
tableタグの内側でRowと書かれていた物で。
[/編集]

[ メッセージ編集済み 編集者: るぱん 編集日時 2004-09-30 17:07 ]
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-09-30 20:30
 他のMLでも解答を書きましたが、上記に記載されたページを見て、keyとfor-eachを使えば、(他のMLで示した自分の解よりも)もっと綺麗に書けることに気がつきました。以下のような感じでしょうか。

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="data_name" match="data" use="name" />

<xsl:output indent="yes" />

<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>

<xsl:template match="data">
<xsl:if test="not(name = preceding-sibling::data/child::name)">
<table>
<xsl:for-each select="key('data_name', name)">
<Row>
<xsl:apply-templates />
</Row>
</xsl:for-each>
</table>
</xsl:if>
</xsl:template>

</xsl:stylesheet>
koko
会議室デビュー日: 2004/04/22
投稿数: 3
投稿日時: 2004-10-01 16:17
kokoでございます。
皆様ありがとうございます。

これまでに、ご教示いただきました内容を参考にして
keyとfor-eachで解決することができました!
本当に助かりました。(もっと勉強いたします...)

ちなみに、今回の XSLT は XML→XMLでしたので、
表の行に相当するタグは<td>にはしておりません。
最初に説明申し上げるべきでした。
以後は気をつけたいと思います。

今後とも、何卒宜しくお願い申し上げます。
1

スキルアップ/キャリアアップ(JOB@IT)