2012-09-25 14 views
5

giriş XML dönüşümXSLT birleştirme/tek bir düğüm halinde aynı adı kardeşlerinin düğüm değerleri bitiştirme

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id><xsl:value-of select="@id"/></id> 
        <name><xsl:value-of select="name"/></name> 
        <category><xsl:value-of select="category" /></category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 
</xsl:stylesheet> 

Gerçek çıkış XML için

<catalog> 
    <product id="1"> 
     <name>abc</name> 
     <category>aaa</category> 
     <category>bbb</category> 
     <category>ccc</category> 
    </product> 
    <product id="2"> 
     <name>cde</name> 
     <category>aaa</category> 
     <category>bbb</category> 
    </product> 
</catalog> 

Beklenen çıkış XML

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa,bbb</category> 
    </product> 
</products> 

XSLT: (

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa</category> 
    </product> 
</products> 

Tüm kardeşler düğümünün her 'ürün' altındaki 'kategori' adıyla girilmesi ve virgülle ayrılmış tek bir düğümde birleştirilmesi/birleştirilmesi gerekir. 'Kategori' sayısı her ürüne göre değişir ve dolayısıyla sayım bilinmemektedir.

cevap

8

here tanımlanan bu kullanışlı katılmak çağrı şablonu kullanarak, bu kadar basit olur:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id> 
         <xsl:value-of select="@id"/> 
        </id> 
        <name> 
         <xsl:value-of select="name"/> 
        </name> 
        <category> 
         <xsl:call-template name="join"> 
          <xsl:with-param name="list" select="category" /> 
          <xsl:with-param name="separator" select="','" /> 
         </xsl:call-template> 
        </category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 

    <xsl:template name="join"> 
     <xsl:param name="list" /> 
     <xsl:param name="separator"/> 

     <xsl:for-each select="$list"> 
      <xsl:value-of select="." /> 
      <xsl:if test="position() != last()"> 
       <xsl:value-of select="$separator" /> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Çıktı:

yalnızca koduna küçük bir değişiklik yapmak gerekir XSLT 2.0
<products> 
    <product> 
    <id>1</id> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <id>2</id> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</products> 
6

:

<category><xsl:value-of select="category" separator=","/></category> 

Bir XSLT 1.0 çözümüne gereksiniminiz varsa, bunun bir Bunu söylemek için iyi bir fikir. Bazı ortamlardaki bazı insanlar 1.0'da kalıyor, ancak birçok insan yok.

+0

Ah evet, onun 1.0 ve xslt stil sayfası sürümü öyle diyor. – user1677271

+1

Stil sayfasındaki sürüm numarası, kullandığınız XSLT işlemcisinin yetenekleri veya projenin daha güncel bir işlemciye geçme kapasitesi hakkında hiçbir şey ifade etmiyor. –

3

İşte bir başka XSLT 1.0 çözümü.

<catalog> 
    <product id="1"> 
    <name>abc</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    <category>ccc</category> 
    </product> 
    <product id="2"> 
    <name>cde</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    </product> 
</catalog> 

... istenilen sonucu üretilen::

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

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

    <xsl:template match="product"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[not(self::category)]" /> 
     <category> 
     <xsl:apply-templates select="category/text()" /> 
     </category> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="category/text()"> 
    <xsl:if test="position() &gt; 1">,</xsl:if> 
    <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

... OP'ın orijinal XML uygulanır: Bu XSLT

<?xml version="1.0"?> 
<catalog> 
    <product> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</catalog> 

Açıklama:

  • ilk şablon - Identity Template - olduğu gibi sonuç belgesine bütün düğümleri ve özelliklerinizi kopya onları eşleşir.
  • İkinci şablon, yeni bir <category> öğesi oluşturarak ve belgenin geçerli konumuna her <category> öğesinin metinlerini işleyerek Kimlik Şablonunu geçersiz kılar.
  • Son şablon, metin değerlerini ve virgülleri gerektiği şekilde verir.
+0

Denemedim ama farklı çözümler için teşekkür ederim ABach :) – user1677271