XSLT

2015-04-17 34 views
6

ile bölünmüş ve düz düğümler İç içe geçmiş bir açılımım olamaz, bu nedenle onları sınıflandırmalarını ve sınıf özniteliklerini birleştirmem gerekir, böylece hangi sınıfların ebeveyn olduğunu izleyebilirim. böylece bile alma,XSLT

İşte
<body> 
    <h1 class="section">Title</h1> 
    <p class="main"> 
     ZZZ 
     <span class="a"> 
      AAA 
      <span class="b"> 
       BBB 
       <span class="c"> 
        CCC 
        <preserveMe> 
         eeee 
        </preserveMe> 
       </span> 
       bbb 
       <preserveMe> 
        eeee 
       </preserveMe> 
      </span> 
      aaa 
     </span> 
    </p> 
</body> 

istenen çıktı üretmesi

<body> 
    <h1 class="section">Title</h1> 
    <p class="main"> 
     ZZZ 
     <span class="a"> 
      AAA 
     </span> 
     <span class="ab"> 
      BBB 
     </span> 
     <span class="abc"> 
      CCC 
      <preserveMe> 
       eeee 
      </preserveMe> 
     </span> 
     <span class="ab"> 
      bbb 
      <preserveMe> 
       eeee 
      </preserveMe> 
     </span> 
     <span class="a"> 
      aaa 
     </span> 
    </p> 
</body> 
İşte

ben geldim, en yakın olduğu (Ben buna gerçekten yeniyim var:

İşte basitleştirilmiş giriş var bu uzak uzun zaman aldı ...)

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
     <p> 
      <xsl:apply-templates/> 
     </p> 
    </xsl:template> 

    <xsl:template match="*/span"> 
     <span class='{concat(../../@class,../@class,@class)}'> 
      <xsl:value-of select='.'/> 
     </span> 
     <xsl:apply-templates/> 
    </xsl:template> 

</xsl:stylesheet> 

Hatalı denememin sonucunu ve kendiniz çalıştırırsanız gerçekten istediğim noktadan ne kadar uzakta olduğunu görebilirsiniz. İdeal olarak, iç içe geçmiş düzeylerin keyfi sayısını kabul eden ve ayrıca kesintili yuvaları (span, span, notSpan, span ...) işleyebilen bir çözüm istiyorum.

düzenleme: İstek üzerine belirtilen yorumcular için iç içe geçmiş yapının içine etiket ekledim. Ayrıca, XSLT v1.0 kullanıyorum, ancak gerekirse diğer sürümleri kullanabilirim.

düzenleme 2: Örneğimin gerçekten dönüştürmem gerekenlerle karşılaştırıldığında aşırı çerçevelendiğini fark ettim. Yani, diğer etiketlerden sınıfları kaybedemem; sadece açıklıklar birleştirilebilir.

+0

Göründüğü kadar karmaşık olabilir: bir yayılma metni dışındaki düğümleri içerebilir mi? "Kesilmiş yuvalardan" bahsediyorsunuz, fakat kesinti noktalarının nereye gitmesi gerekiyor? –

+1

Evet, bir span diğer (notSpan) düğümleri içerebilir ve eğer mümkünse korunmalıdır (ana açıklık düğümleri içinde). Temel olarak, kesinti yapan düğümler, hiç düğüm olmadıkları gibi ele alınmalıdır (düz metinmiş gibi). Tek çözüm bunu başaramazsa, başka düğümlerin de bölünebileceğini düşünüyorum. – DocBuckets

+1

Korkarım cevabını gerçekten anlamıyorum. Örneğinizi, örneğin, her bir metin() için bir span 'oluştururken, diğer senaryoların nasıl korunacağını açıklamalısınız, farklı senaryoları –

cevap

3

yardımcı olabilecek umut çıktı

<hmtl> 
    <body> 
     <p> 
      <span class="a"> 
      AAA 
      </span> 
      <span class="ab"> 
       BBB 
      </span> 
      <span class="abc"> 
       CCC 
       <preserveMe> 
       eeee 
       </preserveMe> 
      </span> 
      <span class="ab"> 
       bbb 
       <preserveMe> 
        eeee 
       </preserveMe> 
      </span> 
      <span class="a"> 
       aaa 
      </span> 
     </p> 
    </body> 
</hmtl> 

var önemsiz. İşte düşünebileceğiniz başka bir yaklaşım:

XSLT 1.

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<!-- identity transform --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="p"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()|.//span/text()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="span/text()"> 
    <span> 
     <xsl:attribute name="class"> 
      <xsl:for-each select="ancestor::span"> 
       <xsl:value-of select="@class"/> 
      </xsl:for-each> 
     </xsl:attribute> 
     <xsl:apply-templates select="preceding-sibling::*"/> 
     <xsl:value-of select="." /> 
     <xsl:if test="not(following-sibling::text())"> 
      <xsl:apply-templates select="following-sibling::*"/> 
     </xsl:if> 
    </span>  
</xsl:template> 

<xsl:template match="span"/> 

</xsl:stylesheet> 

Bu 0 önceki Lingamurthy CS tarafından önerildi ne benzer büyük ölçüde - ama aşağıdaki test girişi ile fark göreceksiniz:

XML

<body> 
    <h1 class="section">Title</h1> 
    <p class="main"> 
     ZZZ 
     <preserveMe>0</preserveMe> 
     <span class="a"> 
      AAA 
      <span class="b"> 
       BBB 
       <span class="c"> 
        CCC 
        <preserveMe>c</preserveMe> 
       </span> 
       bbb 
       <preserveMe>b</preserveMe> 
      </span> 
      aaa 
     </span> 
     <preserveMe>1</preserveMe> 
    </p> 
</body> 
0

aşağıdaki stil yardımcı olur umut: Burada

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <!-- Identity transform template --> 
    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="p"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | text() | .//text()[parent::span]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="text()[parent::span]"> 
     <span> 
      <xsl:attribute name="class"> 
       <xsl:call-template name="class-value"/> 
      </xsl:attribute> 
      <xsl:value-of select="."/> 
      <xsl:apply-templates select="following-sibling::node()[1][not(self::text()) and not(self::span)]"/> 
     </span> 
    </xsl:template> 

    <xsl:template name="class-value"> 
     <xsl:for-each select="ancestor::span/@class"> 
      <xsl:value-of select="."/> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Bu oldukça yakınlaşıyor. Bununla birlikte, tüm eski düz etiketlerin her biri doğru düzleştirilmiş açıklığın dışında çoğalır. Bunu nasıl düzelteceğimi anlayana kadar bir Regex ile tamir edebilirim ... Bunun neden olabileceği hakkında bir fikrin var mı? – DocBuckets

+1

@DocBuckets "* Bununla birlikte, tüm eski düz etiketlerin her biri doğru düzleştirilmiş açıklığın dışında çoğalır. * Bunu görmüyorum. Buradakilerden farklı bir sonuç alıyor musunuz: http://xsltransform.net/6qVRKwu? –

+0

Gerçek işaretlemede denediğimde yaptım, ama şimdi fark ettim ki <12sl: template match = "/ p"> '12 satırındaki atama. Gerçek dosyamın diğer üst etiketleri var, Kodu uygun şekilde ayarlayın. Yarın işte tekrar test edeceğim ve işe yaramazsa cevabı kabul edeceğim. – DocBuckets

0

sen .. İki params almak yuvalanmış açıklıklı şablon tarafından yinelemeli yaptığını ettik ilk sınıfları bitiştirmek için geçerli span class olduğunu ve geçerli aralık düğümü. Sonra iç içe yayılmış alanları işleyin.

Yani sadece root için şablon bizim durumumuzda yayılma etiketi p altında yayılan diyoruz.

<xsl:template match="/"> 
    <hmtl> 
    <body> 
    <p> 
    <xsl:for-each select='.//p/span'> 
     <xsl:call-template name='nested-span'> 
      <xsl:with-param name='cclass' select='./@class'></xsl:with-param> 
      <xsl:with-param name='cspan' select='.'></xsl:with-param> 
     </xsl:call-template> 
    </xsl:for-each> 
    </p> 
    </body> 
    </hmtl> 
</xsl:template> 

<xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 


<xsl:template name="nested-span"> 
     <xsl:param name='cclass'/> 
     <xsl:param name='cspan' as='node()' /> 
     <span> 
       <xsl:attribute name='class' select='$cclass'/> 
       <xsl:value-of select='$cspan/text()[1]' /> 
       <xsl:if test="not(exists(./span))"> 
        <xsl:if test='string-length($cspan/text()[2]) &gt; 0 '> 
         <xsl:value-of select='$cspan/text()[2]' /> 
        </xsl:if> 
        <xsl:apply-templates select="./*[local-name() != 'span']"/> 
       </xsl:if> 
     </span> 

     <xsl:for-each select='$cspan/span'> 
      <xsl:call-template name='nested-span'> 
       <xsl:with-param name='cclass' select='concat($cclass, ./@class)' ></xsl:with-param> 
       <xsl:with-param name='cspan' select='.'></xsl:with-param> 
      </xsl:call-template> 
     </xsl:for-each> 


     <xsl:if test="exists(./span)"> 
      <span>  
       <xsl:attribute name='class' select='$cclass'/> 
        <xsl:if test='string-length($cspan/text()[2]) &gt; 0 '> 
         <xsl:value-of select='$cspan/text()[2]' /> 
        </xsl:if> 
       <xsl:apply-templates select="./*[local-name() != 'span']"/> 
      </span> 
     </xsl:if>  
</xsl:template> 

Ve bu olmaktan uzaktır, ben açılış yorumlarında belirtildiği gibi bu

+0

Bu, 'span' içinde 2'den fazla metin düğümleri için çalışacak gibi görünmüyor. –

+0

Cevabımı güncelledi, Çok teşekkürler. –

0

XSLT 2.0 'un uygun bir seçenek olabileceğini söylediğim gibi, düğüm gruplandırmasına dayalı bir yaklaşım denedim:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="* | @* | text()"> 
     <xsl:copy> 
      <xsl:apply-templates select="* | @* | text()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="span"> 
     <xsl:for-each-group select="* | text()" group-adjacent="name() = 'span'"> 
      <xsl:choose> 
       <xsl:when test="current-group()/self::span"> 
        <!-- a group of span elements: nothing to do yet --> 
        <xsl:apply-templates select="current-group()"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <!-- a group of text nodes and no-span elements: create span --> 
        <span class="{string-join((ancestor::span/@class), '')}"> 
         <xsl:apply-templates select="current-group()"/> 
        </span> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each-group> 
    </xsl:template> 

</xsl:stylesheet> 

önemli noktalar: bir span elemanının

  • çocuk metin düğümleri ve diğer elementler, her ikisi de bu span s olup göre gruplandırılır veya
  • Michael's solution
  • aynı çıkış üretir