2012-04-21 7 views
2

特定の順序で(それを持つノードの)属性を処理する必要があります。例えば:私はそれらを必要とするようXSLプロセスの属性を順番に

<test> 
    <event 
     era ="modern" 
     year ="1996" 
     quarter = "first" 
     day = "13" 
     month= "January" 
     bcad ="ad" 
     hour ="18" 
     minute = "23" 
     >The big game began.</event> 
    <happening 
     era ="modern" 
     day = "18" 
     bcad ="ad" 
     month= "February" 
     hour ="19" 
     minute = "24" 
     >The big game ended.</happening> 
    <other>Before time existed.</other> 
</test> 

この

<xsl:template match="test//*"> 
    <div> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

は、物事をフォーマットします。つまり、私は得るでしょう

<div><span class="era">modern</span> 
    <span class="year">1996</span> 
    <span class="quarter">first</span> 
    <span class="day">13</span> 
    <span class="month">January</span> 
    <span class="bcad">ad</span> 
    <span class="hour">18</span> 
    <span class="minute">23</span>The big game began.</div> 
<div><span class="era">modern</span> 
    <span class="day">18</span> 
    <span class="bcad">ad</span> 
    <span class="month">February</span> 
    <span class="hour">19</span> 
    <span class="minute">24</span>The big game ended.</div> 
<div>Before time existed.</div> 

(但し、ここではわかりやすくするために改行を追加していません)。

しかし、属性の順序は必ずしも正しいとは限りません。

それを修正するには、私は<xsl:call-template name="atts" />から<xsl:apply-templates select="@*" />を変更することができますし、このように、必要に応じて順番にテンプレートを適用するテンプレートを追加します。

<xsl:template match="test//*"> 
    <div> 
     <xsl:call-template name="atts" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template name="atts"> 
    <xsl:apply-templates select="@era" /> 
    <xsl:apply-templates select="@bcad" /> 
    <xsl:apply-templates select="@year" /> 
    <xsl:apply-templates select="@quarter" /> 
    <xsl:apply-templates select="@month" /> 
    <xsl:apply-templates select="@day" /> 
    <xsl:apply-templates select="@hour" /> 
    <xsl:apply-templates select="@minute" />   
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

は、指定された順序で属性を処理するために、このベストプラクティスの方法です?私はキーやグローバル変数を使う方法があるのか​​疑問に思っています。

私はXSLT 1.0を使用する必要があります。実際のケースでは、8個だけでなく数十個の属性があります。

答えて

1

要素とは対照的に、XMLの属性の順序は重要ではありません。つまり、XPathとXSLTは、任意の順序で属性の順序を処理できます。したがって、指定された順序を強制する唯一の方法は、何とかそれを指定することです。 1つの方法は、最後のコード例のように明示的に呼び出すことです。また、すべての属性名を抽出して、別々のXMLファイルに格納することもできます。

<attributes> 
    <attribute>era</attribute> 
    <attribute>year</attribute> 
    <attribute>month</attribute> 
    ... 
<attributes> 

のようなものは、今、あなたは、ドキュメント()関数で、これらの要素をロードして、すべての属性要素反復処理することができますに属性のリストを置く必要がないことを除いて

<xsl:variable name="attributes" select="document('attributes.xml')//attribute"/> 
... 
<xsl:template match="*"> 
    <xsl:variable name="self" select="."/> 
    <xsl:for-each select="$attributes"> 
    <xsl:apply-templates select="$self/@*[name()=current()]"/> 
    </xsl:for-each>  
</xsl:template> 
+0

を別のXMLファイル - XSLTファイルそのものに直接アクセスすることができます(そして、引数なしでdocument()関数を使用して参照する必要があります) –

+0

はい、そうです。与えられたXMLファイルからそれらを抽出するスタイルシートを書いてください。 o属性を抽出して再順序付けするたびに、すべてをスタイルシートにコピーするのではなく、別のファイルにそのようなリストを保持する。しかしそれはたぶん個人的な好みです。 – Martin

+0

@Martin各属性間に区切り文字を追加する方法は分かりますか? apply-templateがちょうど値を返し、属性が月、日、年であったとしましょう。私は "5/16/2012"が好きです。あなたのアプローチでは、pos()!= last()をテストすることはできません。これらの関数は、name()= current()の場合だけでなくfor-eachのすべての属性を数えるからです。 – JPM

関連する問題