QA@IT

変数の値がリセットされません。

11400 PV

初めて質問させていただきます。
よろしくお願いいたします。

XSL2.0でxsl:for-eachを使用した変換を行ったのですが、その中で使用する変数の値に不可解な値が挿入されてしまいます。
1回目の処理は問題ないのですが、2回目の処理以降、該当値が重複(1であれば11、2であれば22)した値となってしまいました。
これは何が問題であるか、ご教授いただけないでしょうか。

サンプルXMLは以下のとおりです。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="ForQuestion.xsl" type="text/xsl" ?>
<!DOCTYPE root SYSTEM "C:\Users\plants\Desktop\InDesignTest\ForQuestion.dtd" []>
<root>
    <topics>
        <topic> **…(1回目のtopic)**
            <intro contents="5">                
                <entry name="Gibson" num="1"/>
                <entry name="Morris" num="2"/>
                <entry name="MARTIN" num="3"/>
                <entry name="Taylor" num="4"/>
                <entry name="FURCH" num="5"/>               
                <description>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content>ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content salename="Gibson">aaa and bbb</content>
                        <content>ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content salename="Morris">bbb and ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content salename="MARTIN">ccc and ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content>ccc</content>
                        <content salename="Taylor">ddd and eee</content>
                    </detail>
                </description>
            </intro>
        </topic>
        <topic> **…(2回目のtopic)**
            <intro contents="5">                
                <entry name="Gibson" num="1"/>
                <entry name="Morris" num="2"/>
                <entry name="MARTIN" num="3"/>
                <entry name="Taylor" num="4"/>
                <entry name="FURCH" num="5"/>               
                <description>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content>ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content salename="Gibson">aaa and bbb</content>
                        <content>ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content salename="Morris">bbb and ccc</content>
                        <content>ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content salename="MARTIN">ccc and ddd</content>
                        <content>eee</content>
                    </detail>
                    <detail>
                        <content>aaa</content>
                        <content>bbb</content>
                        <content>ccc</content>
                        <content salename="Taylor">ddd and eee</content>
                    </detail>
                </description>
            </intro>
        </topic>
    </topics>
</root>

XSLの該当部分を以下に抜粋します。

<xsl:template match="content">

        <xsl:param name="feat"><xsl:value-of select="@salename"/></xsl:param> **…(A)**

        <xsl:variable name="featured_num" as="xs:integer"> **…(B)**
            <xsl:for-each select="preceding::entry"> **…(C)**

                <xsl:variable name="maker">
                    <xsl:value-of select="@name"/>
                </xsl:variable>             

                <xsl:if test="$feat = $maker">
                    <xsl:value-of select="number(@num)"/>
                </xsl:if>

            </xsl:for-each>
        </xsl:variable>

        <!-- 変数確認のため下記1行を挿入 -->
        <p><xsl:value-of select="$featured_num"/></p>

    </xsl:template>

以下、xslでやろうとしていることです。

(A)contentにmatchしたら、contentの属性値「salename」を変数「feat」に格納します。
属性値が無い場合はそのまま無視させています。

(B)変数「featured_num」を取得します。(取得方法は以下Cを参照)

(C)xsl:for-eachで、XMLソースの前半にあるentry要素(このサンプルでは5つ)のname属性(=変数maker)と、content要素のsalename属性(=変数feat)を比較し、一致した場合には、entry要素のnum属性を上記(B)の変数「featured_num」の値とします。

これを実行させると、1回目のtopicでは「1」「2」「3」「4」の値が得られるのですが、2回目のtopicでは「11」「22」「33」「44」という不可解な値になってしまいます。

表示される結果は以下のとおりです。
result.png

回数を重ねるたびに重複が増えていきます。
これは何が原因でしょう。リセットする方法は無いでしょうか。
entryを参照させるためにXPathの「preceding::」を使用していますが、これがマズイのでしょうか。

よろしくご教授のほど、お願いいたします。
なお、質問の仕方や資料不足があればご指摘ください。改めさせていただきます。

回答

entryを祖先のintro配下に絞ってみてはどうでしょう。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xs">


    <xsl:template match="content">
        <xsl:param name="feat"><xsl:value-of select="@salename"/></xsl:param>
        <xsl:if test="$feat != ''">
            <xsl:variable name="featured_num" as="xs:string">
                <xsl:for-each select="ancestor::intro/entry">

                    <xsl:variable name="maker">
                        <xsl:value-of select="@name"/>
                    </xsl:variable>

                    <xsl:if test="$feat = $maker">
                        <xsl:value-of select="number(@num)"/>
                    </xsl:if>

                </xsl:for-each>
            </xsl:variable>

            <!-- 変数確認のため下記1行を挿入 -->
            <p><xsl:value-of select="$featured_num"/></p>
        </xsl:if>
        <xsl:if test="$feat = ''">
            <!-- <p>not found.</p> -->
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
 
1

2

3

4

 
1

2

3

4
編集 履歴 (0)
  • ありがとうございました。
    問題解決いたしました。
    「content」から見た「entry」が祖父の兄弟に当たるので、対応するXPathの軸には「preceding::」しか使えないと思っていました。
    XPathについて、今一度勉強いたします。
    本当にありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。