2

私は探し回りましたが、私が見つけたアイデアをうまく​​機能させることができませんでした。

これらは、xml ファイル (db から生成される) にあるいくつかのノードです。

<PANELS>        
<PANEL ATTR1="7"  ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8"  ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8A" ATTR2="37" ATTR3="31"/>
</PANELS>
<ZONES>
<ZONE ATTR1="7"  ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8"  ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8A" ATTR2="37" ATTR3="31" />
</ZONES>

これらのそれぞれから個別の ATTR3 を選択できるようにしたいと考えています。

現在、これは最初のもので機能し、 //PANELS/PANEL[not(@ATTR3 = (preceding::*/@ATTR3))] 「31」の期待される結果を返します

しかし、2番目のものに対して同じことをしようとすると、何も返されません(もう一度「31」を返したい) //ZONES/ZONE[not(@ATTR3 = (preceding::*/@ATTR3))]

ATTR3 の値がそれらすべてで同じであるため、2 番目のものが機能しないことは理解していますが、ノードごとに個別の属性値を取得するにはどうすればよいですか?

(これは、個別の値を表示するために使用している for-each の述語として使用されています)

これは、このように使用されています。これらの 1 つはゾーンfor-each用で、もう 1 つはパネル用です

<xsl:for-each select="//PANELS/PANEL[not(@ATTR3 = (preceding::*/@ATTR3))]">
<xsl:sort select="@ATTR3"/>
<xsl:value-of select="@ATTR3" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>

返してほしい

PANELS: 31

ZONES: 31

preceding-siblingの代わりに使ってみましprecedingたが、

PANELS: 31, 31

ZONES: 31

それぞれが次のようなテンプレートになっています。

    <xsl:template match="//HEADER/ZONES" >              
    <fo:block font-size="10pt">
        <fo:table  table-layout="fixed" > 
            <fo:table-column column-width="proportional-column-width(1)"/>
            <fo:table-column column-width="proportional-column-width(7)"/>
            <fo:table-body>
                <fo:table-row>
                    <fo:table-cell  border-bottom="none">
                        <fo:block font-weight="bold">
                            <xsl:text>Zones:</xsl:text>
                        </fo:block>
                    </fo:table-cell >                       
                    <fo:table-cell>
                        <fo:block>
                            <xsl:for-each select="//HEADER/ZONES/ZONE[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
                                <xsl:sort select="@ATTR3"/>
                                <xsl:value-of select="@ATTR3" />
                                <xsl:if test="position()!=last()">, </xsl:if>
                            </xsl:for-each>
                        </fo:block>
                    </fo:table-cell>
                </fo:table-row>             
            </fo:table-body>
        </fo:table>
    </fo:block>
    </xsl:template>
4

2 に答える 2

3

次の XSLT は31preceding-siblingsの代わりに使用precedingするため、正しい回数の繰り返しが生成されます。

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

    <xsl:output method="text"/>

    <xsl:template match="//HEADER/ZONES">
        ZONES:
        <xsl:for-each select="//ZONES/ZONE[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
            <xsl:sort select="@ATTR3"/>
            <xsl:value-of select="@ATTR3" />
            <xsl:if test="position()!=last()">, </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="//HEADER/PANELS">
        PANELS:
        <xsl:for-each select="//PANELS/PANEL[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
            <xsl:sort select="@ATTR3"/>
            <xsl:value-of select="@ATTR3" />
            <xsl:if test="position()!=last()">, </xsl:if>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

このドキュメントの出力:

<HEADER>
    <PANELS>
        <PANEL ATTR1="7"  ATTR2="37" ATTR3="31"/>
        <PANEL ATTR1="8"  ATTR2="37" ATTR3="31"/>
        <PANEL ATTR1="8A" ATTR2="37" ATTR3="31"/>
    </PANELS>
    <ZONES>
        <ZONE ATTR1="7"  ATTR2="37" ATTR3="31" />
        <ZONE ATTR1="8"  ATTR2="37" ATTR3="31" />
        <ZONE ATTR1="8A" ATTR2="37" ATTR3="31" />
    </ZONES>
</HEADER>

以下のとおりであります:

    ZONES:
    31
    PANELS:
    31
于 2012-07-06T14:39:54.310 に答える
1

この短く (13 行) 単純な変換 -- テンプレートは 1 つだけで、ハードコーディングされた文字列はありません

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text" />
 <xsl:strip-space elements="*"/>

 <xsl:template match="t/*[*/@ATTR3]">
     <xsl:value-of select="concat(name(), ':')"/>
     <xsl:for-each select="*/@ATTR3[not(. = ../preceding-sibling::*/@ATTR3)]">
       <xsl:value-of select="concat(' ', .)"/>
     </xsl:for-each>
     <xsl:text> </xsl:text>
 </xsl:template>
</xsl:stylesheet>

提供された XML (整形式になるように単一のトップ要素にラップされた) ドキュメントに適用された場合:

<t>
    <PANELS>
        <PANEL ATTR1="7"  ATTR2="37" ATTR3="31"/>
        <PANEL ATTR1="8"  ATTR2="37" ATTR3="31"/>
        <PANEL ATTR1="8A" ATTR2="37" ATTR3="31"/>
    </PANELS>
    <ZONES>
        <ZONE ATTR1="7"  ATTR2="37" ATTR3="31" />
        <ZONE ATTR1="8"  ATTR2="37" ATTR3="31" />
        <ZONE ATTR1="8A" ATTR2="37" ATTR3="31" />
    </ZONES>
</t>

必要な正しい結果が生成されます。

PANELS: 31 ZONES: 31 
于 2012-07-06T14:48:59.947 に答える