2014-01-24 5 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> («буква», «число», «буква номера»)?

А в случае, когда число содержит число, как написать шаблон с < 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 вы хотите один def_group для каждого sn, который начинается с номером:

<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> 

двойной перевод еще одна идиома - это способ, чтобы удалить все символы из строки кроме в конкретном «белом списке», поэтому в этом случае вычеркивать все небуквенные символы из строки.

Смежные вопросы