2012-07-02 49 views
1

嗨,我是一名初學者,希望學習XSLT。 我偶然發現了一個問題,使用XSLT輸入的XML文件轉換爲其他XML文件使用xslt將輸入xml轉換爲其他XML

我輸入XML文件:

<album> 
<album_num>hi.hello</album_num> 
<album_name>Cocktail</album_name> 
</album> 
<album> 
<album_num>hey.hello</album_num> 
<album_name>Mocktail</album_name> 
</album> 
<album> 
<album_num>hey.mello</album_num> 
<album_name>Monkeytail</album_name> 
</album> 
<album> 
<album_num>hey.yellow</album_num> 
<album_name>Donkeytail</album_name> 
</album> 
<album> 
<album_num>swallow</album_num> 
<album_name>abc</album_name> 
</album> 

我想獲得一個輸出XML文件:

<album> 
<album_num> 
<hi> 
<hello>cocktail</hello> 
</hi> 
</album_num> 
<album_num> 
<hey> 
<hello>MockTail</hello> 
<mello>Monkeytail</mello> 
<yellow>Donkeytail</yellow> 
</hey> 
</album_num> 
<album_num> 
<swallow>abc</swallow> 
</album_num> 
</album> 

我通過創建變量嘗試了第一部分。但是在合併一個元素下的相似元素時遇到了問題。任何代碼都可以幫助我學習。提前致謝。

我的代碼:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="/"> 
<album> 
<xsl:variable name="fstval" select='substring-before(//album/album_num,".")'/> 
<xsl:variable name="secval" select='substring-after(//album/album_num,".")'/> 
<xsl:variable name="valtoappend" select='//album/album_name'/> 
<album_num> 
<xsl:element name="{$fstval}"> 
<xsl:element name="{$secval}"> 
<xsl:value-of select="$valtoappend"/> 
</xsl:element> 
</xsl:element> 
</xsl:for-each> 
</album_num> 
</album> 
</xsl:template> 
</xsl:stylesheet> 

回答

1

該轉化

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/> 

<xsl:template match="/"> 
    <xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates/> 
    </xsl:variable> 

    <xsl:apply-templates mode="pass2" select= 
    "ext:node-set($vrtfPass1)/* 
      [generate-id() 
      = 
      generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1]) 
      ] 
    "/> 
</xsl:template> 

<xsl:template match="album"> 
    <album> 
    <album_num> 
     <xsl:element name="{substring-before(album_num, '.')}"> 
     <xsl:element name="{substring-after(album_num, '.')}"> 
      <xsl:value-of select="album_name"/> 
     </xsl:element> 
     </xsl:element> 
    </album_num> 
    </album> 
</xsl:template> 

<xsl:template match="album" mode="pass2"> 
    <album> 
    <album_num> 
     <xsl:apply-templates select="*/*[1]" mode="pass2"/> 
    </album_num> 
    </album> 
</xsl:template> 

<xsl:template match="album_num/*" mode="pass2"> 
    <xsl:copy> 
    <xsl:copy-of select="key('kAlbumByChildName', name())/*/*/*"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當在以下文檔(包裝在單個頂部元件所提供的XML片段施加使之成爲很好 - 形成的XML文檔):

<t> 
    <album> 
     <album_num>hi.hello</album_num> 
     <album_name>Cocktail</album_name> 
    </album> 
    <album> 
     <album_num>hey.hello</album_num> 
     <album_name>Mocktail</album_name> 
    </album> 
    <album> 
     <album_num>hey.mello</album_num> 
     <album_name>Monkeytail</album_name> 
    </album> 
    <album> 
     <album_num>hey.yellow</album_num> 
     <album_name>Donkeytail</album_name> 
    </album> 
</t> 

產生想要的,正確的結果:

<album> 
    <album_num> 
     <hi> 
     <hello>Cocktail</hello> 
     </hi> 
    </album_num> 
</album> 
<album> 
    <album_num> 
     <hey> 
     <hello>Mocktail</hello> 
     <mello>Monkeytail</mello> 
     <yellow>Donkeytail</yellow> 
     </hey> 
    </album_num> 
</album> 

說明

這是一個雙通道改造。第一遍的結果是

<album> 
    <album_num> 
     <hi> 
     <hello>Cocktail</hello> 
     </hi> 
    </album_num> 
</album> 

<album> 
    <album_num> 
     <hey> 
     <hello>Mocktail</hello> 
     </hey> 
    </album_num> 
</album> 

<album> 
    <album_num> 
     <hey> 
     <mello>Monkeytail</mello> 
     </hey> 
    </album_num> 
</album> 

<album> 
    <album_num> 
     <hey> 
     <yellow>Donkeytail</yellow> 
     </hey> 
    </album_num> 
</album> 

第二遍是標準Muenchian分組的。

更新:提出這個問題,並接收正確答案後

兩天,OP改變了源XML文檔,想要的結果。當在XML文檔新版本的應用

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vrtfPass1"> 
     <xsl:apply-templates/> 
     </xsl:variable> 

     <xsl:apply-templates mode="pass2" select= 
     "ext:node-set($vrtfPass1)/* 
       [generate-id() 
       = 
       generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1]) 
       or 
       not(album_num/*) 
       ] 
     "/> 

    </xsl:template> 

    <xsl:template match="album[contains(album_num, '.')]"> 
     <album> 
     <album_num> 
      <xsl:element name="{substring-before(album_num, '.')}"> 
      <xsl:element name="{substring-after(album_num, '.')}"> 
       <xsl:value-of select="album_name"/> 
      </xsl:element> 
      </xsl:element> 
     </album_num> 
     </album> 
    </xsl:template> 

    <xsl:template match="album"> 
     <album> 
     <album_num> 
      <xsl:element name="{album_num}"> 
       <xsl:value-of select="album_name"/> 
      </xsl:element> 
     </album_num> 
     </album> 
    </xsl:template> 

    <xsl:template match="album" mode="pass2"> 
     <album> 
     <album_num> 
      <xsl:apply-templates select="*/*[1]" mode="pass2"/> 
     </album_num> 
     </album> 
    </xsl:template> 

    <xsl:template match="album_num/*" mode="pass2"> 
     <xsl:copy> 
     <xsl:copy-of select="self::*[not(*)]/text()|key('kAlbumByChildName', name())/*/*/*"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

這略微修改後的轉換

<t> 
    <album> 
     <album_num>hi.hello</album_num> 
     <album_name>Cocktail</album_name> 
    </album> 
    <album> 
     <album_num>hey.hello</album_num> 
     <album_name>Mocktail</album_name> 
    </album> 
    <album> 
     <album_num>hey.mello</album_num> 
     <album_name>Monkeytail</album_name> 
    </album> 
    <album> 
     <album_num>hey.yellow</album_num> 
     <album_name>Donkeytail</album_name> 
    </album> 
    <album> 
     <album_num>swallow</album_num> 
     <album_name>abc</album_name> 
    </album> 
</t> 

產生新的通緝的結果

<album> 
    <album_num> 
     <hi> 
     <hello>Cocktail</hello> 
     </hi> 
    </album_num> 
</album> 
<album> 
    <album_num> 
     <hey> 
     <hello>Mocktail</hello> 
     <mello>Monkeytail</mello> 
     <yellow>Donkeytail</yellow> 
     </hey> 
    </album_num> 
</album> 
<album> 
    <album_num> 
     <swallow>abc</swallow> 
    </album_num> 
</album> 
+0

謝謝迪米特雷。我很高興爲像我這樣的初學者提供幫助。 – Ramana

+0

@Ramana:我很高興我的回答對你有幫助。您能否請*接受*(通過點擊答案旁邊的複選標記)? –

+0

@Ramana:請參閱此答案的更新 - 它解決了您修改的問題。你不覺得你必須*接受*這個答案嗎? –