- PR -

xsltにおいて子ノードのマッチングで親ノードの結合方式

投稿者投稿内容
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-05-30 18:01
root
以下のようなxmlがあります。

┣親ノード1      
┃┣子ノード1
┃┣子ノード2
┃┗子ノード3
┣親ノード2      
┃┣子ノード1
┃┣子ノード2
┃┗子ノード4
┗親ノード3
 ┣子ノード1
 ┣子ノード2
 ┗子ノード4

親ノード1/子ノード1 = 親ノード2/子ノード1 かつ
親ノード1/子ノード2 = 親ノード2/子ノード2
のとき
┣親ノード1      
┃┣子ノード1
┃┣子ノード2
┃┣子ノード3
┃┗子ノード4
┗親ノード3
 ┣子ノード1
 ┣子ノード2
 ┗子ノード4

ということを行いたいのです。
ただしxmlを作る必要は無く、Webに表示(htmlが出れば)できればよいのですが
何とかならないものでしょうか?
子ノード1、子ノード2でソートすれば今一歩というところまで
いくのですが、後一歩が踏み出せません。
お知恵をお貸しください。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-05-31 10:49
検索語 は XSLT 集約
要素の集約(2)
http://qa.xml.gr.jp/data/xsl/files/0048.xml

XPath2.0 の distinct
データ用のXML: XPath 2.0の新機能
http://www-06.ibm.com/jp/developerworks/xml/021206/j_x-xdxpath2.html
↑ 古いかも、こんな感じ、
データ型、名前空間と がっぷり四つ なので、難産。
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-05-31 12:01
助かりました。
絶対できるだろうと思っていたのですが、
なかなか探せないで苦労していたところです。

お礼だけでは、なんですので私のほうもひとつ裏技を。
Microsoft.XMLDOM + XSLT + javascriptで

reslst.innerHTML = objDoc.transformNode(objXSLT);

こんなことやりますよね。
これが、

document.write(objDoc.transformNode(objXSLT));
とできます。(当たり前?)

もう一歩進んで
var fso = new ActiveXObject("Scripting.FileSystemObject");
var a = fso.CreateTextFile("c:\\testfileS.txt", true);

a.Write(objDoc.transformNode(objXSLT));

なんてこともできちゃいます。(マイクロソフト恐るべし、これってトロイの・・・)
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-06-01 11:21
う〜ん、いまいちだな。
http://qa.xml.gr.jp/data/xsl/files/0048.xml を多少作り変え、

2つのノードをマッチングさせるとき、
<xsl:for-each select="record[((not(id = preceding-sibling::record/id))or(not(data = preceding-sibling::record/data)))]">

でその数だけは検出してくれるのですが、
<xsl:for-each select="key('id', id)">と
<xsl:for-each select="key('data', data)">の
組み合わせ方がわかりませんね。
考え方としては、id とdataのどちらかが異なるものを行変えの対象とし、
idとdataがまったく同じものを、その行に追加していくと考えているのですが
いまひとつ得たいものがしっくり来ません。
id とdata を一組としてキーにできればうまく行くのでしょうが、
規約を読んでも理解力の無さに参っています。

以下ソース
-----(test.xml)
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="test2.xsl"?>
<database>
<record>
<id>#1</id>
<data>a</data>
<aaa>1</aaa>
</record>
<record>
<id>#1</id>
<data>a</data>
<bbb>8</bbb>
</record>
<record>
<id>#1</id>
<data>b</data>
<aaa>2</aaa>
</record>
<record>
<id>#1</id>
<data>b</data>
<bbb>2</bbb>
</record>
<record>
<id>#2</id>
<data>c</data>
<aaa>2</aaa>
</record>
<record>
<id>#2</id>
<data>c</data>
<bbb>5</bbb>
</record>
<record>
<id>#3</id>
<data>d</data>
<aaa>2</aaa>
</record>
<record>
<id>#3</id>
<data>d</data>
<bbb>8</bbb>
</record>
<record>
<id>#4</id>
<data>d</data>
<aaa>2</aaa>
</record>
<record>
<id>#4</id>
<data>d</data>
<bbb>10</bbb>
</record>
</database>

---test2.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:key name="id1" match="record" use="id" />
<xsl:key name="data1" match="record" use="data" />
<xsl:output method="html" encoding="Shift_JIS" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="database">

<TABLE BORDER="1">
<TR>
<TD>ID</TD>
<TD>data</TD>
<TD>aaa</TD>
<TD>bbb</TD>
</TR>

<xsl:for-each select="record[((not(id = preceding-sibling::record/id))or(not(data = preceding-sibling::record/data)))]">
<xsl:if test="aaa">
<TR>
<TD><xsl:value-of select="id"/></TD>
<TD><xsl:value-of select="data"/></TD>
<TD><xsl:value-of select="aaa"/></TD>

<xsl:for-each select="key('data1', data)">
<xsl:if test="bbb">
<TD><xsl:value-of select="bbb"/></TD>
</xsl:if>
</xsl:for-each>
</TR>
</xsl:if>
</xsl:for-each>
</TABLE>

</xsl:template>
</xsl:stylesheet>
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-06-02 05:59
id+dataでひとつのノードを新規に作成した中間ファイルを作って
解決しました。
しかし、時間に追われていたとはいえ、情けない。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-06-02 13:52
仕様を読んでおくと、ギリギリの粘りがつきます、犠牲者と生還者の違い。

<!-- Category: top-level-element -->
<xsl:key
name = qname
match = pattern
use = expression />

use は 単項ではなく、式を書ける。concat(id,data) とか、
中間ファイルを作るのは、けっこう 武勇伝、武勇伝。

[ メッセージ編集済み 編集者: MMX 編集日時 2006-06-04 10:16 ]
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-06-05 11:09
あっちゃんかっこいい(w

ただ、10万件ほどのXMLで行ったら時間のボトルネックに引っかかりました。
処理時間の問題はつらい。
やっぱりDBに入れることを考えます。

しかしWebを立てず、フリーソフトの範囲で、IEのセキュリティレベル高でという要求を
受けた私が馬鹿だった。
虐めとしか思えない要求じゃ・・・・
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-06-05 11:30
Office 2007 ベータ は 期間限定の フリー かも
OpenOffice2.0 の Base もDBですが。
参考
HTA(JavaScript) で作るのなら Revight エディタ あたりが限界点。

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