2014-01-24 54 views
0

我有XML等,使得我不能改變如何在XSLT中將兄弟作爲孩子包含在內?

<entry> 
    <sn>1 a</sn> 
    <dt>:to run away often from danger or evil</dt> 
    <sn>b</sn> 
    <dt>:to hurry toward a place of security</dt> 
    <sn>2</sn> 
    <dt>:to pass away swiftly</dt> 
</entry> 

我試圖寫XSLT來得到它看起來像這樣

<div class="entry"> 
     <div class="def_group"> 
      <span class="def_group_number">1</span> 
      <div class="def_value"> 
       <span class="def_value_letter">a</span> 
       <span class="the_def">:to run away often from danger or evil</span> 
      </div> 

      <div class="def_value"> 
       <span class="def_value_letter">b</span> 
       <span class="the_def">:to hurry toward a place of security</span> 
      </div> 
     </div> 

     <div class="def_group"> 
      <span class="def_group_number">2</span> 
      <div class="def_value"> 
       <span class="the_def">:to pass away swiftly</span> 
      </div> 
     </div> 
    </div> 

當我打破它,我有兩個問題真的。

如何使用XSLT 1.0分開< sn> (「letter」,「number」,「number letter」)這三種情況?

而且,在包含數字的情況下,如何編寫一個帶有< div>的模板,該模板將包含它的兄弟< dt>作爲孩子?

回答

1

XSLT 1.0對字符串操作並不好,但我認爲可以這樣做。首先,我們將需要找到所有的字母sn s表示屬於頭號,所以我們定義爲

<xsl:key name="subsenseByMainSense" 
    match="sn[not(number(substring(., 1, 1)) = number(substring(., 1, 1)))]" 
    use="generate-id(preceding-sibling::sn[ 
      number(substring(., 1, 1)) = number(substring(., 1, 1))][1])" /> 

關鍵這看起來很奇怪,但它的所有成語 - 的number() = number()是一種檢查問題(這裏是節點的字符串值的第一個字符)是否是一個數字。如果你檢查一個數字,那麼測試是檢查一個數字是否與自己相等,這總是正確的;如果它是而不是一個數字,那麼測試是NaN = NaN,它總是假的。

現在從entry開始你想爲以數字開頭的每個sn一個def_group

<xsl:template match="entry"> 
    <div class="entry"> 
    <xsl:apply-templates select="sn[number(substring(., 1, 1)) 
            = number(substring(., 1, 1))]" /> 
    </div> 
</xsl:template> 

<xsl:template match="sn"> 
    <div class="def_group"> 
    <span class="def_group_number"> 
     <xsl:choose> 
     <xsl:when test="contains(., ' ')"> 
      <xsl:value-of select="substring-before(., ' ')"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="." /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </span> 

    <!-- do the value(s) of this element and any following letter-only ones --> 
    <xsl:apply-templates mode="value" 
     select=". | key('subsenseByMainSense', generate-id())" /> 
    </div> 
</xsl:template> 

現在的價值位,如果這個元素有一個字母,然後添加一個def_value_letter,否則只是the_def

<xsl:template match="sn" mode="value"> 
    <xsl:variable name="letter" 
    select="translate(., translate(., 'abcdefghijklmnopqrstuvwxyz', ''), '')" /> 
    <div class="def_value"> 
    <xsl:if test="$letter"> 
     <span class="def_value_letter"> 
     <xsl:value-of select="$letter" /> 
     </span> 
    </xsl:if> 
    <span class="the_def"> 
     <xsl:value-of select="following-sibling::dt[1]" /> 
    </span> 
    </div> 
</xsl:template> 

的雙轉換爲另一個成語 - 這是一種從一個字符串刪除所有字符,除了那些在特定的「白名單」,所以在這種情況下,去除字符串中的所有非字母字符。