例えば

<title>タイトルA</title>
<P>no1</P>
<P>no2</P>
<P>no3</P>
<P>no4</P>
<title>タイトルB</title>
<P>no5</P>
<P>no6</P>
<P>no7</P>
<P>no8</P>

というようなxmlがあったとします。

xslを適用して、
タイトルA
no1
no2
no3
no4
タイトルB
no5
no6
no7
no8
と表示するにはどのようにすればよいのでしょうか?

<xsl:for-each select="//P">
 <P><value-of select="."/></P>
</xsl:for-each>

ではnoのみが表示され、タイトルが表示されず、また、

<xsl:for-each select="//title">
 <P><xsl:value-of select="."/></P>
 <xsl:for-each select="../P">
  <P><xsl:value-of select="."/></P>
 </xsl>
</xsl>

では、
タイトルA
no1
no2
no3
no4
no5
no6
no7
no8
タイトルB
no1
no2
no3
no4
no5
no6
no7
no8

となってしまいます。

A 回答 (1件)

 だいぶ経ってしまっているので、回答が役に立つのか分かりませんが、


一応書いておきます。

 正確な意図が分かりにくいので、この回答が見当違いかもしれません。


<xsl:for-each select="//title">
 <P><xsl:value-of select="."/></P>
 <xsl:for-each select="../P">
  <P><xsl:value-of select="."/></P>
 </xsl>
</xsl>

と記述しようとしている場所に

<xsl:apply-templates select="//title | //P"/>

と記述しておいて、

<xsl:template match="title">
 <!-- title要素に対する処理 -->
</xsl:template>

<xsl:template match="P">
 <!-- P要素に対する処理 -->
</xsl:template>

というテンプレートを呼び出すようにすれば良いのでは?

 もちろん、apply-templatesでtitle要素とP要素を区別しない点が
意図と異なるかもしれませんが。


 この場合のデータ構造があまり良くないので、例えば

<Group>
 <title>タイトルA</title>
 <P>no1</P>
 <P>no2</P>
 <P>no3</P>
 <P>no4</P>
</Group>
<Group>
 <title>タイトルB</title>
 <P>no5</P>
 <P>no6</P>
 <P>no7</P>
 <P>no8</P>
</Group>

のようにデータ構造をより良いものにしてから、
という手もあります。
こうするとだいぶ処理が楽になります。


 最後に、余計な忠告かもしれませんが、
xsl:for-eachにこだわり過ぎないで柔軟に考えた方が良いのでは、
と私は思います。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Q

の使い方

xhtml+cssをやり始めです。

実は、<br />と<p></p>の使い方についてわかんなくて教えてくださーい。

普通のhtmlでは改行したいときは、<br />を入れまくっていましたが、xhtmlは<br/>ではなく改行は<p></p>でといわれました。

<p>あいうえお</p>
<p>かきくけこ</p>

といれると改行にはなりますが、1行あけたい場合はどうしますか?

<p>あいうえお</p>
<p></p>
<p>かきくけこ</p>

としても1行あきませんよね?
こういう場合は

<p>あいうえお</p>
<br />
<p>かきくけこ</p>

でいいのですかね???

単純な質問ですみません。

Aベストアンサー

基本的に、<p>タグで段落を作るときに、勝手に一行開けてくれると考えていいかと思います。
そして、<br>は行をあけない普通の改行ということになります。

つまり、一行あけるときは
<p>あいうえお</p>
<p>かきくけこ</p>

行をあけないときは
<p>あいうえお<br />
かきくけこ</p>
となります。

*余談ながら、xhtmlでは<body>の直下に普通のテキストを書くことができませんので、文章を書くときはそれを<p>で囲ってやることが必要となります。

Q単独

お世話になります。

現在、サンプルのXSLTスタイルシート内を解析中なのですが、
各テンプレート内に、
<xsl:apply-templates />という単独での要素が、
いくつも出てきます。

ネット上で調べてみたところ、
「ほかのテンプレートの処理に移ることが出来る」
ということのようですが、
いまいち、この単独での要素を、
記述する意味が、よくわかりません。
(最近、XSLTを本で勉強しはじめたばかりなのですが、
  その本には、”<xsl:apply-templates select="mains">”みたいな例しか掲載されておらず、
  <xsl:apply-templates />という単独での説明が、残念ながら存在しておりませんでした・・・)

そこでご質問内容ですが、
XSLTスタイルシート内のテンプレート内に、
<xsl:apply-templates />という単独で、
で記述するのは、
どのようなことを実現させたいときに、
記述しているのでしょうか?

以上になります。
出来ましたら、例などを出していただきまして、
具体的に理解しやすく教えていただけますと
助かります。
どうぞよろしくお願いします。

お世話になります。

現在、サンプルのXSLTスタイルシート内を解析中なのですが、
各テンプレート内に、
<xsl:apply-templates />という単独での要素が、
いくつも出てきます。

ネット上で調べてみたところ、
「ほかのテンプレートの処理に移ることが出来る」
ということのようですが、
いまいち、この単独での要素を、
記述する意味が、よくわかりません。
(最近、XSLTを本で勉強しはじめたばかりなのですが、
  その本には、”<xsl:apply-templates select="mains">”みたいな例しか掲載されておらず、
  <xs...続きを読む

Aベストアンサー

わからないときは、仕様で確認するといいかも。
「select 属性が無いときは、カレントノードの全ての子ノード」ってかいてあったよ?

5.4 Applying Template Rules - XSL Transformations (XSLT)
→ http://www.w3.org/TR/xslt/#section-Applying-Template-Rules

「In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.」


だから、
select="node()"
の省略とみなして、いい気がする。

Qとtopreceding-siblingを使ったグループ化

下記のxmlを

<xml xmlns:s="uuid:#dummy#" xmlns:dt="#dummy#" xmlns:rs="#dummy#" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="COUNTRY" rs:number="1" rs:nullable="true" rs:writeunknown="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="4" rs:fixedlength="true"/>
</s:AttributeType>
<s:AttributeType name="NAME" rs:number="2" rs:writeunknown="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="9" rs:fixedlength="true" rs:maybenull="false"/>
</s:AttributeType>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row COUNTRY="JAPAN" NAME="TARO" AGE="12"/>
<z:row COUNTRY="JAPAN" NAME="JIRO" AGE="23"/>
<z:row COUNTRY="CHINA" NAME="SABURO" AGE="34"/>
</rs:data>
</xml>

下記のxslを使用してCOUNTRY毎にグルーピングして
csv形式で出力したいですが以下のxslだとうまくいきません。

<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

<xsl:key name="COUNTRY" match="//z:row" use="@COUNTRY" />

<xsl:template match="/">

<xsl:for-each select="//z:row[not(@COUNTRY = preceding-sibling:://z:row/@COUNTRY)]">
<xsl:value-of select="@COUNTRY" />,<xsl:value-of select="@NAME" />,<xsl:value-of select="@AGE" />
</xsl:for-each>

</xsl:template>
</xsl:stylesheet>

[欲しい結果]
JAPAN,TARO
JAPAN,JIRO
スペース
CHINA,SABURO

下記のxmlを

<xml xmlns:s="uuid:#dummy#" xmlns:dt="#dummy#" xmlns:rs="#dummy#" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="COUNTRY" rs:number="1" rs:nullable="true" rs:writeunknown="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="4" rs:fixedlength="true"/>
</s:AttributeType>
<s:AttributeType name="NAME" rs:number="2" rs:writeunknown="true">
<s:dat...続きを読む

Aベストアンサー

#1>"c:\windows\system32\msxml3.dll"にしなければいけないのではないか
あんまり詳しくはないのですが、私は、IE6で動作確認しています。
IE6は、msxml3.dllは使ってなかった(別途ダウンロードしてインストールしなければいけなかったような気がします)と思います。
質問文のXSLで欲しい結果にならない理由がDLLだという意味なら、
それは、違うと思います。
select="//z:row[not(@COUNTRY = preceding-sibling:://z:row/@COUNTRY)]">
でセレクトされるのは、それまでとCOUNTRYがことなるもの
つまり
JAPAN,TARO
CHINA,SABURO
の2つのデータをセレクトすることを意味していると思われるからです。
#1>XMLのデバッグにはどのような方法があるのでしょうか?
この時のこの値という意味なら、開発環境でインスペクトすればいいと思いますが、
構文エラーが表示されるので、まずは、IEで動作させてみるのがいいと思います。
例えば、質問文のXSLであれば、
xmlns:xsl="http://www.w3.org/TR/WD-xsl"に「xsl:keyがない」
ネームスペース「z:」が定義されていないとか表示されます。
あとついでに言えば、<xsl:key>宣言は、xsl:templateの中で使われていないので必要ないと思います。

#1>"c:\windows\system32\msxml3.dll"にしなければいけないのではないか
あんまり詳しくはないのですが、私は、IE6で動作確認しています。
IE6は、msxml3.dllは使ってなかった(別途ダウンロードしてインストールしなければいけなかったような気がします)と思います。
質問文のXSLで欲しい結果にならない理由がDLLだという意味なら、
それは、違うと思います。
select="//z:row[not(@COUNTRY = preceding-sibling:://z:row/@COUNTRY)]">
でセレクトされるのは、それまでとCOUNTRYがことなるもの...続きを読む

Qスタイルシートのfor-each select=に変数を使用したい

お世話になります。

<xsl:param name="A" select="1000">



<xsl:template name="B">



<xsl:for-each select=".//1000"> -(1)
</xsl:template>

<xsl:template match="1000"> -(2)
</xsl:template>

(1)
(1)の箇所の「1000」を上で宣言したAを使用したく、
<xsl:for-each select="concat('.//',$A")> 
など色々試したのですが、うまくいきませんでした。
(2)
(2)の箇所を「A」の変数に色々な形で置き換えてもうまくいきませんでした。

上記2点、を変数を使用して指定したいのですが、どのようにすれば実現できますでしょうか?

大変お手数とは思いますがよろしくお願いします。

Aベストアンサー

<xsl:for-each select=".//1000"> -(1)
これでは,変数にする以前の問題として,まともに動かないのでは?
要素名の一文字目は数字にはできません。xpathも大丈夫でしょうか?
まず,変数にする前にきちんと動くようにしたとして,次に変数にするには,環境によって難易度が異なります。

xalanのようにdyn:evaluate()が使えるものは,要素名を変数に文字列として入れて,これをevaluate関数でノードセットに戻します。
概念的には,
 <xsl:variable name="hensu" select="'s1000'"/>
として,要素名を''で囲んで,文字列としてhensuに格納します。
これを使うときは,
 <xsl:for-each select="dyn:evaluate($hensu)">
などとしますが,evaluateの引数は,パーサによって異なります。

なお,msxmlは,そのまんまではevaluateを使えません。

次に,<xsl:template match="1000"> -(2)ですが,これを変数化するのは不可能だと思います。
match内のxpath表現をランタイムで変更できる仕様はないと思います(多分)。

variableもparamも,xsltの変数は,通常のプログラム言語の変数と異なり,とても制限が多く,使いづらいものなのです。

<xsl:for-each select=".//1000"> -(1)
これでは,変数にする以前の問題として,まともに動かないのでは?
要素名の一文字目は数字にはできません。xpathも大丈夫でしょうか?
まず,変数にする前にきちんと動くようにしたとして,次に変数にするには,環境によって難易度が異なります。

xalanのようにdyn:evaluate()が使えるものは,要素名を変数に文字列として入れて,これをevaluate関数でノードセットに戻します。
概念的には,
 <xsl:variable name="hensu" select="'s1000'"/>
として,要素名を''...続きを読む

Qxsl:param要素をxsl:templateのmatch属性で使用するには?

xsl:param要素をxsl:templateのmatch属性で使用するにはどうしたらよいでしょうか?
あるいは、そんなことはできないという情報でも結構です。ご教示ください。

Aベストアンサー

なるほど。補足していただいた説明で、質問の意味は分かりました。

XSLTの仕様上は、xsl:stylesheetの子要素としてxsl:param要素を置いた場合、そこから後ろのxsl:templateでは参照できるはずです。

そこで、以下のような短いXSLTスタイルシートを用意して、
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="n" select="test"/>
<xsl:template match="abc[@attr=$n]">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="@* | text()"></xsl:template>
</xsl:stylesheet>

以下のXMLファイルに適用してみたところ、
<data>
<abc attr="test1">item1</abc>
<abc attr="test">item2</abc>
<abc attr="test2">item3</abc>
</data>

Xalanでは正しく item2 と出力されました。
しかしXTでは、何も出力されず、XTのオプションで n=test のようにパラメータを設定すると、正しく出力されました。
私の解釈では、Xalanの動作の方が正しいような気がします。

したがって、もしXTを使っているならば、この実装上の違いが原因かと思われます。
この場合、XTの作者に直してもらうか、Xalanなど別のXSLTプロセッサを使うしか、解決方法はないかもしれません。

なるほど。補足していただいた説明で、質問の意味は分かりました。

XSLTの仕様上は、xsl:stylesheetの子要素としてxsl:param要素を置いた場合、そこから後ろのxsl:templateでは参照できるはずです。

そこで、以下のような短いXSLTスタイルシートを用意して、
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="n" select="test"/>
<xsl:template match="abc[@attr=$n]">
<xsl:value-of select="."/>
</xsl:template>
<xsl:...続きを読む


おすすめ情報