2011-01-24 20 views
8

Belirli koşullara uyulursa, düğümleri XSLT kullanarak bir seviye yukarı taşımayı öğrenmek istiyorum. Bir örnek vermek gerekirse şu XML kaynağında bir göz:XSLT: Düğüm bir seviye yukarı git

durumun başlangıç ​​olarak ben XML olduğunu
<Settings> 
    <String [...]> 
    <Boolean [...]/> 
    </String> 
</Settings> 

. Açık olması gerekirse, düğüm adları "Ayarlar", "Dize", "Boole", tanımladığımız özel düğümlerdir.

Sorun, "Boole" düğümlerinin "Dize" düğümlerinin içine girmesine izin verilmemesidir. Bu yüzden bu "Boolean" düğümlerini yukarı kaldırmak zorundayım. İstenilen XML şu şekilde görünecektir:

<Settings> 
    <String [...]></String> 
    <Boolean [...]/> 
</Settings> 

XSLT da ne olursa olsun XML ağacında konumu nedeniyle, bir kardeş Boole düğümü olan her dize düğümü ile çalışmak zorundadır.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   
    xmlns:fo="http://www.w3.org/1999/XSL/Format" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions"> 

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

    <!-- special rules ... --> 

</xsl:stylesheet> 

Ben ile mücadele ediyorum şeydir:

Şimdiye kadar ilk istenilen dönüşümleri için bazı özel kurallar geçerlidir daha sonra bir "kimlik kuralı" kullanarak XML tüm kopyalayıp zorunda öğrendik "String" düğümlerinin kardeşleri olan tüm "Boolean" düğümlerini bir seviye yukarı kaldırmaya karar ver. Bunu nasıl yapabilirim?!?

+0

İyi soru, +1. "Kimlik kuralını geçersiz kıl" tasarım deseninin bir varyasyonu için cevabımı görün - biraz daha doğru bir geçersiz kılma sağladım. :) –

cevap

6

Benim çevirim

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

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

<xsl:template match="String"> 
    <xsl:copy> 
     <xsl:apply-templates select="child::node()[not(self::Boolean)]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="Boolean"/> 
</xsl:template> 

</xsl:stylesheet> 
+1

Teşekkür ederim Michael. Cevabınız iyi görünüyor.Sadece tek bir küçük değişiklik önereceğini: olur Bu değişiklikle, Dize düğümlerinin öznitelikleri de kopyalanır. Çok teşekkür ederim. – Jens

+0

+1 Doğru cevap. –

3

Aşağıdakileri deneyin: ihtiyacının

<!-- copy all --> 
<xsl:template match="*"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

<!-- ignore booleans-inside-strings --> 
<xsl:template match="String/Boolean" /> 

<!-- place the booleans-inside-strings into the settings element --> 
<xsl:template match="Settings"> 
    <xsl:copy> 
     <xsl:copy-of select="//String/Boolean" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 
+1

"Tümünü kopyala" şablonunda "match =" @ * | node() "' ve 'select =" @ * | node() "' neden olmamasının bir nedeni var mı? Sadece merak ediyorum ... – Filburt

+0

Cevabınız için teşekkür ederiz. Bu benim örneğim için iyi çalışıyor. Fakat her zaman çalışmayacaktır, çünkü Boole düğümünü her zaman ayarlar öğesine kopyalar. Kural, Boolean öğesini bir seviye yukarı kopyalamalıdır. dönüşümü olmalıdır düşünün: Ayrıca Jens

+0

, neden başlangıç ​​'//' '// Dizi/Boolean' içinde? –

3

Bu çözüm Michae-Kay @ o oldukça benzer olarak çözümünü verir. Ancak, kimlik kuralının ağır basan biraz daha hassas - gerçekten bir Boolean çocuk var sadece String elemanları eşleştirildiği:

<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="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="String[Boolean]"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()[not(self::Boolean)]|@*"/> 
    </xsl:copy> 
    <xsl:apply-templates select="Boolean"/> 
</xsl:template> 
</xsl:stylesheet> 

bu dönüşümün aşağıdaki XML belgesinin karşı uygulandığında:

<Settings> 
    <String> 
     <Boolean /> 
    </String> 
    <String/> 
</Settings> 

aranan, doğru sonuç üretilir:

<Settings> 
    <String/> 
    <Boolean/> 
    <String/> 
</Settings> 
+0

ayrıca cevabıma bir bakabilir misiniz? İndirgemeye değer bir hata bulamıyorum. Kendisini reddetme umurumda değil, sadece bir kaç guru kaçırıp kaçırmadığımı görmek istiyorum. – Flack

+0

@Flack: Çözümünüzün iyi olduğunu düşünüyorum. Şablonları yalnızca 'Setings' özelliklerine uygulamanız yeterlidir - aksi takdirde kaybolurlar. Cevabınızı destekledim, ancak lütfen bu önerilen düzeltmeyi de ekleyin. –

+0

OP'nin sağladığı örneklem nedeniyle bilinçli bir ihmal oldu. Her ne kadar daha iyi tasarlanmış iki tane olduğu için cevabımı kaldırmayı seçtim. Tabii ki geri dönüş. Mevcut oyların respawn için bekliyordum. – Flack