2011-05-21 26 views
5

rtf stil sayfasına xsl-fo oluşturuyorum. Elimdeki problemlerden biri de xsl-fo belgesindeki sayısız ölçü birimini twip'e (rtf ölçü birimi) dönüştürmektir.xsl dönüştür/çevir şablonu

kod

özel bir parça sütun genişlikleri caluclates:

<xsl:value-of select="sum(preceding-sibling: 
    :fo:table-column/@column-width) + @column-width"/> 

... sorun /@column-width değeri, bu nedenle zaman 20px (20 piksel) için 1in (1 inç) bir şey olabilir olmak Toplamı başarısız olurum.

ben bir şekilde bir twip eşdeğerdir için @column-width dönüştürmek gerekir

: 1pt = 19.95 twips, 1px = 15 twips, 1pc = 240 twips, 1in = 1440 twips, 1cm = 567 twips, 1mm = 56.7 twips, 1em = 240 twips

muhtemelen dönüştürme yapabilirsiniz bir yöntem yazabilir, ama ben eminim yapmak translate() fonksiyonun faydalanmak için bazı yol var Bu çok daha etkilidir.

ayırın, benim xsl tüm bu büyük değil, bu yüzden bunu başarmak için nasıl bir örnek İstediğim şey bulmayı başardılar

DÜZENLEME

takdir edilecektir ama hiçbir fikrim yok

<xsl:template match="@*" mode="convert-to-twips"> 
    <xsl:variable name="scaling-factor"> 
     <xsl:choose> 
     <xsl:when test="contains (., 'pt')">19.95</xsl:when> 
     <xsl:when test="contains (., 'px')">15</xsl:when> 
     <xsl:when test="contains (., 'pc')">240</xsl:when> 
     <xsl:when test="contains (., 'in')">1440</xsl:when> 
     <xsl:when test="contains (., 'cm')">567</xsl:when> 
     <xsl:when test="contains (., 'mm')">56.7</xsl:when> 
     <xsl:when test="contains (., 'em')">240</xsl:when> 
     <!-- guess: 1em = 12pt --> 
     <xsl:otherwise>1</xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="numeric-value" 
     select="translate (., '-.ptxcinme', '-.')"/> 
    <xsl:value-of select="$numeric-value * $scaling-factor"/> 

</xsl:template> 
+0

İyi soru, +1. Tam ve kolay bir çözüm için cevabımı görün. –

+0

Evet, ve bu bir * tam * çözümdür - sadece sözde kod değil. call-template': –

+0

Benim cevabım size 'xsl kullanarak şablon kuralını nasıl kullanabileceğine ilişkin sadece bir örnektir olmak istiyor. Translate'yi nasıl kullandığınız konusunda da küçük bir hata var. Cevabımı gör, umarım yardımcı olur. Flynn1179 @ –

cevap

3

Bu dönüşümü:

yukarıdaki hesaplamada bu şablonu çağırmak için nasıl Aşağıdaki XML belgesine uygulanan
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
xmlns:fo="some:fo" xmlns:my="my:my" > 
<xsl:output method="text"/> 

<my:units> 
    <unit name="pt">19.95</unit> 
    <unit name="in">1440</unit> 
    <unit name="cm">567</unit> 
    <unit name="mm">56.7</unit> 
    <unit name="em">240</unit> 
    <unit name="px">15</unit> 
    <unit name="pc">240</unit> 
</my:units> 

<xsl:variable name="vUnits" select= 
     "document('')/*/my:units/*"/> 

<xsl:template match="/"> 
    <xsl:apply-templates select="*/*/*/@column-width"/> 
</xsl:template> 

<xsl:template match="@column-width"> 
    <xsl:variable name="vQuantity" select= 
     "substring(.,1, string-length() -2)"/> 
    <xsl:variable name="vUnit" select= 
     "substring(., string-length() -1)"/> 

    <xsl:variable name="vrtfAccumWidth"> 
    <num>0</num> 
    <xsl:for-each select= 
    "../preceding-sibling::fo:table-column/@column-width"> 
    <xsl:variable name="vQ" select= 
     "substring(.,1, string-length() -2)"/> 
    <xsl:variable name="vU" select= 
     "substring(., string-length() -1)"/> 

    <num> 
     <xsl:value-of select= 
     "$vQ * $vUnits[@name=$vU]"/> 
    </num> 
    </xsl:for-each> 
    </xsl:variable> 

    <xsl:value-of select= 
    "$vQuantity * $vUnits[@name=$vUnit] 
    + 
    sum(ext:node-set($vrtfAccumWidth)/num) 
    "/> 

    <xsl:text>&#xA;</xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

(hiçbiri sağlandı olarak!):

39.9 
2919.9 
4053.9 
4167.3 
4647.3 
4677.3 
5157.3 

Bildirimi:

<fo:fo xmlns:fo="some:fo"> 
<fo:table> 
    <fo:table-column column-width="2pt"/> 
    <fo:table-column column-width="2in"/> 
    <fo:table-column column-width="2cm"/> 
    <fo:table-column column-width="2mm"/> 
    <fo:table-column column-width="2em"/> 
    <fo:table-column column-width="2px"/> 
    <fo:table-column column-width="2pc"/> 
</fo:table> 
</fo:fo> 

aranan, doğru sonucu üretir: fo:table-column\@column-width büyük bir dizi için daha verimli bir çözüm gerekirse, o zaman FXSL - scanl template/function kullanılabilir - tam bir kod örneği için önceki soruya verdiğim yanıtı bakın.

+0

: My aritmetik * ise "kolayca" yanlış :) –

+0

Evet, zaten fark ve benim yorum sildi olurdu olduğu ortaya dönüşebilir kolay görünebilir neler bazen * Doğru ve; Noktasının, sütunların genişliğini hesaplamak olduğunu söylediği yerde, kümülatif olması beklenmediğini düşündüğü soruyu yanlış anladım. – Flynn1179

+0

@ Flynn1179: Sorun değil, dostum. Hepimiz insanız ve en azından bazen hata yapıyoruz :) –

1

Sen sahip mevcut bir faydalanmak için bu şablonu kullanabilirsiniz:

<xsl:template match="@column-width"> 
    <xsl:variable name="previous"> 
    0<xsl:apply-templates select="../preceding-sibling::*[1]/@column-width" /> 
    </xsl:variable> 
    <xsl:variable name="this"> 
    <xsl:apply-templates select="." mode="convert-to-twips"/> 
    </xsl:variable> 
    <xsl:value-of select="$previous + $this" /> 
</xsl:template> 

sadece şimdiki birine ekleyerek daha sonra, önceki sütunların genişliğini hesaplayarak, gördüğünüz gibi oldukça basit bu. İlk değişkende <xsl:apply-templates talimatının önünde 0 olduğunu fark edeceksiniz; Bu değişkene geçerli bir sayı verildiğinden emin olmak için. Önceki sütun yoksa, '' yerine '0' kaydedilecektir.

Kesin olarak, varolan şablonunuzun gövdesini ikinci değişkenin yerine ekleyebilir ve en altta <xsl:value-of select="$previous + ($numeric-value * $scaling-factor)" /> olabilir; bu tamamen size kalmış.

1

Ayrıca şablon fonksiyonu ve xsl:call-template ile gidebilirsiniz. @Dimitre giriş örneği çalmak (bana kızma :) Sana xsl:call-template ile dönüşüm şablon kuralını nasıl kullanabileceğinizi gösteriyor. dönüşümü olarak

Ben böylece dönüştürülen değerleri toplama her table-column yineleme. Değeri dönüştürmek için sadece orijinal şablon kuralınızı (biraz ayarlanmış) çağırıyorum. Sonra değerlerin toplamını gerçekleştirmek için sum kullanıyorum. Eğer bir numaraya translate tarafından döndürülen değer dağıtmak yoksa bir XSLT 2.0 uyumlu işlemci çalışma zamanı hatası döndürür

Not. Saxon-B 9.0.0.4J altında test


XSLT 2,0

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

    <xsl:template match="fo:table/fo:table-column"> 

     <xsl:variable name="twips"> 
      <twips> 
       <xsl:for-each select="preceding-sibling::fo:table-column/@column-width"> 
        <twip> 
         <xsl:call-template name="convert-to-twips"> 
          <xsl:with-param name="value" select="."/> 
         </xsl:call-template> 
        </twip> 
       </xsl:for-each> 
       <twip> 
         <xsl:call-template name="convert-to-twips"> 
          <xsl:with-param name="value" select="@column-width"/> 
         </xsl:call-template> 
       </twip> 
      </twips> 
     </xsl:variable> 

     <xsl:value-of select="sum($twips//twip)"/><xsl:text> </xsl:text> 

    </xsl:template> 

    <xsl:template name="convert-to-twips"> 

     <xsl:param name="value"/> 

     <xsl:variable name="scaling-factor"> 
      <xsl:choose> 
       <xsl:when test="contains ($value, 'pt')">19.95</xsl:when> 
       <xsl:when test="contains ($value, 'px')">15</xsl:when> 
       <xsl:when test="contains ($value, 'pc')">240</xsl:when> 
       <xsl:when test="contains ($value, 'in')">1440</xsl:when> 
       <xsl:when test="contains ($value, 'cm')">567</xsl:when> 
       <xsl:when test="contains ($value, 'mm')">56.7</xsl:when> 
       <xsl:when test="contains ($value, 'em')">240</xsl:when> 
       <!-- guess: 1em = 12pt --> 
       <xsl:otherwise>1</xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:variable name="numeric-value" 
      select="number(translate ($value, '-.ptxcinme', '-.'))"/> 
     <xsl:value-of select="$numeric-value * $scaling-factor"/> 

    </xsl:template> 

</xsl:stylesheet> 

Bu girişine uygulanan dönüşüm:

<fo:fo xmlns:fo="some:fo"> 
<fo:table> 
    <fo:table-column column-width="2pt"/> 
    <fo:table-column column-width="2in"/> 
    <fo:table-column column-width="2cm"/> 
    <fo:table-column column-width="2mm"/> 
    <fo:table-column column-width="2em"/> 
    <fo:table-column column-width="2px"/> 
    <fo:table-column column-width="2pc"/> 
</fo:table> 
</fo:fo> 

üretir:

39.9 2919.9 4053.9 4167.3 4647.3 4677.3 5157.3