2014-09-22 17 views
0

基本上,這是一個xlst新手,並且負責處理對處理德國市場電影元數據轉換的大型xls文件的一些更改。XLST 1.0更改值後的輸出中的組元素

XLS文件看起來是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:str="http://exslt.org/strings" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:redirect="http://xml.apache.org/xalan/redirect" extension-element-prefixes="redirect" xmlns:xalan="http://xml.apache.org/xslt" exclude-result-prefixes="xalan str"> 
<xsl:output method="xml" indent="yes" xalan:indent-amount="4"/> 
<xsl:strip-space elements="*"/> 
<xsl:template match="/metadata"> 
    <xsl:variable name="featureID" select="substring(mpm_product_id, 7, string-length(mpm_product_id))"/> 
    <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" /> 
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> 
    <Metadata> 

    <some values...> 

    <xsl:for-each select="genres/genre"> 

        <Genre> 
          <xsl:choose> 

           <!-- Mappings for German Genres --> 
           <xsl:when test="/metadata/base/territory_code='DE'"> 
            <xsl:choose> 

             <xsl:when test=".= 'Action'">Action und Abenteuer</xsl:when> 
             <xsl:when test=".= 'Adventure'">Action und Abenteuer</xsl:when> 
             <xsl:when test=".= 'Animation'">Zeichentrick</xsl:when> 
             <xsl:when test=".= 'Anime'">Zeichentrick</xsl:when> 
             <xsl:when test=".= 'Bollywood'">Bollywood</xsl:when> 
             <xsl:when test=".= 'Classics'">Drama > Klassiker</xsl:when> 
             <xsl:when test=".= 'Comedy'">Komödie</xsl:when> 
             <xsl:when test=".= 'Concert Film'">Musik</xsl:when> 
             <xsl:when test=".= 'Crime'">Kriminalfilm > Drama</xsl:when> 
             <xsl:when test=".= 'Drama'">Drama</xsl:when> 
             <xsl:when test=".= 'Fantasy'">Drama > Sci-Fi und Fantasy</xsl:when> 
             <xsl:when test=".= 'Foreign'">International</xsl:when> 
             <xsl:when test=".= 'Horror'">Kriminalfilm > Horror</xsl:when> 
             <xsl:when test=".= 'Independent'">Independentfilm &amp; Arthouse</xsl:when> 
             <xsl:when test=".= 'Japanese Cinema'">International > Japan</xsl:when> 
             <xsl:when test=".= 'Jidaigeki'">International > Japan</xsl:when> 
             <xsl:when test=".= 'Kids &amp; Family'">Kinderfilm > Familie</xsl:when> 
             <xsl:when test=".= 'Music Documentary'">Musik > Dokumentation</xsl:when> 
             <xsl:when test=".= 'Music Feature Film'">Musik</xsl:when> 
             <xsl:when test=".= 'Musicals'">Musik > Musical</xsl:when> 
             <xsl:when test=".= 'Mystery'">Drama > Mystery</xsl:when> 
             <xsl:when test=".= 'Nonfiction - Documentary'">Dokumentation</xsl:when> 
             <xsl:when test=".= 'Regional Indian'">International > Indien &amp; Pakistan</xsl:when> 
             <xsl:when test=".= 'Romance'">Drama > Romanze</xsl:when> 
             <xsl:when test=".= 'Science Fiction'">Science Fiction und Fantasy</xsl:when> 
             <xsl:when test=".= 'Short Films'">Independentfilm &amp; Arthouse > Experimentalfilm</xsl:when> 
             <xsl:when test=".= 'Special Interest'">Hobby</xsl:when> 
             <xsl:when test=".= 'Sports'">Sport</xsl:when> 
             <xsl:when test=".= 'Thrillers'">Thriller</xsl:when> 
             <xsl:when test=".= 'Tokusatsu'">International > Japan</xsl:when> 
             <xsl:when test=".= 'Urban'">Drama > Alltag</xsl:when> 
             <xsl:when test=".= 'Westerns'">Western</xsl:when> 

             <xsl:otherwise> 
              <xsl:value-of select="." /> 
             </xsl:otherwise> 
            </xsl:choose> 
           </xsl:when> 


          </xsl:choose> 

        </Genre> 
       </xsl:for-each> 
     <More values...> 
    </Metadata> 
</xsl:template> 

問題是當流派都改變了我們與例如重複值結束的時候,輸入包含的元素

<genres> 
    <genre>Comedy</genre> 
    <genre>Adventure</genre> 
    <genre>Action</genre> 
</genres> 

改造後我們有

<Genre>Komödie</Genre> 
<Genre>Action und Abenteuer</Genre> 
<Genre>Action und Abenteuer</Genre> 

我試過尋找一些解決方案,但我還沒有達到解決方案和任何幫助將不勝感激。

編輯澄清:我需要的是從輸出中消除重複的流派元素。這些元素可以不相鄰,我們不能通過第二次轉換來運行輸出,因爲我們無法修改處理此操作的服務的代碼。

感謝

+0

那麼你至少需要告訴我們你想要的結果。你想消除重複的流派元素?只有在他們相鄰的時候,你想這樣做嗎,就像你的樣本,或者他們是分開的?您是否考慮過鏈接兩個樣式表,您只需簡單地通過第二個樣式表運行輸出,以避免Muenchian分組重複出現http://www.jenitennison.com/xslt/grouping/muenchian.xml? – 2014-09-22 18:07:23

+0

理想情況下,需要從列表中刪除重複的流派元素,這些元素並不總是彼此相鄰。也不可能通過第二個樣式表運行輸出。我將通過這些澄清更新這個問題。 – 2014-09-22 18:16:37

+0

您將需要另一個包含「if」條目值的XML,因此您可以使用XPath檢查「前兄弟節點」。 – Xenos 2014-09-22 18:27:55

回答

0

由於您使用Xalan作爲XSLT處理器,您可以使用該處理器支持的幾個擴展函數輕鬆解決此問題。下面是使用EXSLT(你似乎已經被使用,由xmlns:str命名空間的聲明判斷)的例子:

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

xmlns:set="http://exslt.org/sets" 
xmlns:exsl="http://exslt.org/common" 
xmlns:str="http://exslt.org/strings" 

xmlns:xalan="http://xml.apache.org/xslt" 
xmlns:redirect="http://xml.apache.org/xalan/redirect" 

exclude-result-prefixes="set exsl str xalan" 
extension-element-prefixes="redirect"> 

<xsl:output method="xml" indent="yes" xalan:indent-amount="4"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/metadata"> 
    <xsl:variable name="featureID" select="substring(mpm_product_id, 7, string-length(mpm_product_id))"/> 
    <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" /> 
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> 
    <Metadata> 
     <xsl:variable name="genres"> 
      <xsl:for-each select="genres/genre"> 
       <Genre> 
        <xsl:choose> 
         <xsl:when test="/metadata/base/territory_code='DE'"> 
          <xsl:choose> 
           <xsl:when test=".= 'Action'">Action und Abenteuer</xsl:when> 
           <xsl:when test=".= 'Adventure'">Action und Abenteuer</xsl:when> 
           <xsl:when test=".= 'Animation'">Zeichentrick</xsl:when> 
           <xsl:when test=".= 'Anime'">Zeichentrick</xsl:when> 
           <xsl:when test=".= 'Bollywood'">Bollywood</xsl:when> 
           <xsl:when test=".= 'Classics'">Drama > Klassiker</xsl:when> 
           <xsl:when test=".= 'Comedy'">Komödie</xsl:when> 
           <xsl:when test=".= 'Concert Film'">Musik</xsl:when> 
           <xsl:when test=".= 'Crime'">Kriminalfilm > Drama</xsl:when> 
           <xsl:when test=".= 'Drama'">Drama</xsl:when> 
           <xsl:when test=".= 'Fantasy'">Drama > Sci-Fi und Fantasy</xsl:when> 
           <xsl:when test=".= 'Foreign'">International</xsl:when> 
           <xsl:when test=".= 'Horror'">Kriminalfilm > Horror</xsl:when> 
           <xsl:when test=".= 'Independent'">Independentfilm &amp; Arthouse</xsl:when> 
           <xsl:when test=".= 'Japanese Cinema'">International > Japan</xsl:when> 
           <xsl:when test=".= 'Jidaigeki'">International > Japan</xsl:when> 
           <xsl:when test=".= 'Kids &amp; Family'">Kinderfilm > Familie</xsl:when> 
           <xsl:when test=".= 'Music Documentary'">Musik > Dokumentation</xsl:when> 
           <xsl:when test=".= 'Music Feature Film'">Musik</xsl:when> 
           <xsl:when test=".= 'Musicals'">Musik > Musical</xsl:when> 
           <xsl:when test=".= 'Mystery'">Drama > Mystery</xsl:when> 
           <xsl:when test=".= 'Nonfiction - Documentary'">Dokumentation</xsl:when> 
           <xsl:when test=".= 'Regional Indian'">International > Indien &amp; Pakistan</xsl:when> 
           <xsl:when test=".= 'Romance'">Drama > Romanze</xsl:when> 
           <xsl:when test=".= 'Science Fiction'">Science Fiction und Fantasy</xsl:when> 
           <xsl:when test=".= 'Short Films'">Independentfilm &amp; Arthouse > Experimentalfilm</xsl:when> 
           <xsl:when test=".= 'Special Interest'">Hobby</xsl:when> 
           <xsl:when test=".= 'Sports'">Sport</xsl:when> 
           <xsl:when test=".= 'Thrillers'">Thriller</xsl:when> 
           <xsl:when test=".= 'Tokusatsu'">International > Japan</xsl:when> 
           <xsl:when test=".= 'Urban'">Drama > Alltag</xsl:when> 
           <xsl:when test=".= 'Westerns'">Western</xsl:when> 
          <xsl:otherwise> 
           <xsl:value-of select="." /> 
          </xsl:otherwise> 
         </xsl:choose> 
         </xsl:when> 
        </xsl:choose> 
       </Genre> 
      </xsl:for-each> 
     </xsl:variable> 

     <xsl:copy-of select="set:distinct(exsl:node-set($genres)/Genre)"/> 

    </Metadata> 

</xsl:template> 

</xsl:stylesheet> 

應用到你的輸入例如,結果是:

<?xml version="1.0" encoding="UTF-8"?> 
<Metadata> 
    <Genre>Komödie</Genre> 
    <Genre>Action und Abenteuer</Genre> 
    <Genre>B-Grade</Genre> 
</Metadata> 

說明:

恕我直言,你聲明的Xalan namespac E:

xmlns:xalan="http://xml.apache.org/xslt" 

是不正確的,應改爲:

xmlns:xalan="http://xml.apache.org/xalan" 

一旦你解決這個問題,你可以使用類似的功能來自Xalan擴展庫:xalan的:不同的()和Xalan:節點集() (不是它有很大的區別)。

+0

我試過這個,但是它的轉換沒有返回元素 – 2014-09-22 21:20:13

+0

@MiguelArriaga在處理代碼片段時,很難說出問題所在。這對你有用嗎? http://xsltransform.net/jyH9rM2 – 2014-09-22 21:25:35

+0

感謝您的快速反應邁克爾。其實我已經把它和你的建議一起工作了。謝謝 – 2014-09-22 21:40:48

0

應用該XSLT(style.xsl

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:stylesheet 
    xmlns:str="http://exslt.org/strings" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0" 
    xmlns:redirect="http://xml.apache.org/xalan/redirect" 
    extension-element-prefixes="redirect" 
    xmlns:xalan="http://xml.apache.org/xslt" 
    exclude-result-prefixes="xalan str"> 

    <xsl:output method="xml" indent="yes" xalan:indent-amount="4"/> 

    <xsl:strip-space elements="*"/> 

    <xsl:template match="/metadata"> 
     <xsl:variable name="featureID" select="substring(mpm_product_id, 7, string-length(mpm_product_id))"/> 
     <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" /> 
     <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> 

     <Metadata> 
      <xsl:if test="/metadata/base/territory_code='DE'"> 
       <!-- Applying template is the way XSLT works --> 
       <xsl:apply-templates select="genres/genre"> 
        <xsl:with-param name="ifs" select="document('ifs.xml')/ifs"/> 
       </xsl:apply-templates> 
      </xsl:if> 
     </Metadata> 
    </xsl:template> 

    <xsl:template match="genre"> 
     <xsl:param name="ifs"/> 

     <!-- if if/@test=current() then we'll display if/text() --> 
     <xsl:variable name="this-if"  select="$ifs/if[@test=current()]"/> 
     <!-- gets all 'ifs' using previous 'genre' that have same value as $this-if --> 
     <xsl:variable name="previous-if" select="$ifs/if[string(.)=string($this-if) and @test=current()/preceding-sibling::genre]"/> 

     <Genre> 
      <xsl:choose> 
       <xsl:when test="$previous-if"> <!-- Duplicate --> 
        <xsl:text>Node genre=&quot;</xsl:text> 
        <xsl:value-of select="current()"/> 
        <xsl:text>&quot; (if=</xsl:text> 
        <xsl:value-of select="$this-if"/> 
        <xsl:text>; id:</xsl:text> 
        <xsl:value-of select="generate-id()"/> 
        <xsl:text> is a duplicate of if/@test=&quot;</xsl:text> 
        <xsl:value-of select="$previous-if/@test"/> 
        <xsl:text>&quot;</xsl:text> 
       </xsl:when> 
       <!-- Not duplicate + there is a 'if' entry --> 
       <xsl:when test="$this-if"> 
        <xsl:apply-templates select="$this-if"/> 
       </xsl:when> 
       <!-- Not duplicate + there is no 'if' entry --> 
       <xsl:otherwise> 
        <xsl:value-of select="."/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </Genre> 
    </xsl:template> 

    <xsl:template match="if"> 
     <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

此源(source.xml

<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/xsl" href="style.xsl"?> 

<metadata> 
    <base> 
     <territory_code>DE</territory_code> 
    </base> 
    <genres> 
     <genre>Comedy</genre> 
     <genre>Adventure</genre> 
     <genre>Action</genre> 
     <genre>B-Grade</genre> 
    </genres> 
</metadata> 

並使用新的XML文件來處理if小號測試值(ifs.xml ):

<?xml version="1.0" encoding="utf-8"?> 

<ifs> 
    <if test="Action">Action und Abenteuer</if> 
    <if test="Adventure">Action und Abenteuer</if> 
    <if test="Animation">Zeichentrick</if> 
    <if test="Anime">Zeichentrick</if> 
    <if test="Bollywood">Bollywood</if> 
    <if test="Classics">Drama &gt; Klassiker</if> 
    <if test="Comedy">Komödie</if> 
    <if test="Concert Film">Musik</if> 
    <if test="Crime">Kriminalfilm &gt; Drama</if> 
    <if test="Drama">Drama</if> 
    <if test="Fantasy">Drama &gt; Sci-Fi und Fantasy</if> 
    <if test="Foreign">International</if> 
    <if test="Horror">Kriminalfilm &gt; Horror</if> 
    <if test="Independent">Independentfilm &amp; Arthouse</if> 
    <if test="Japanese Cinema">International &gt; Japan</if> 
    <if test="Jidaigeki">International &gt; Japan</if> 
    <if test="Kids &amp; Family">Kinderfilm &gt; Familie</if> 
    <if test="Music Documentary">Musik &gt; Dokumentation</if> 
    <if test="Music Feature Film">Musik</if> 
    <if test="Musicals">Musik &gt; Musical</if> 
    <if test="Mystery">Drama &gt; Mystery</if> 
    <if test="Nonfiction - Documentary">Dokumentation</if> 
    <if test="Regional Indian">International &gt; Indien &amp; Pakistan</if> 
    <if test="Romance">Drama &gt; Romanze</if> 
    <if test="Science Fiction">Science Fiction und Fantasy</if> 
    <if test="Short Films">Independentfilm &amp; Arthouse &gt; Experimentalfilm</if> 
    <if test="Special Interest">Hobby</if> 
    <if test="Sports">Sport</if> 
    <if test="Thrillers">Thriller</if> 
    <if test="Tokusatsu">International &gt; Japan</if> 
    <if test="Urban">Drama &gt; Alltag</if> 
    <if test="Westerns">Western</if> 
</ifs> 

你得到

<Metadata> 
    <Genre>Komödie</Genre> 
    <Genre>Action und Abenteuer</Genre> 
    <Genre>Node genre="Action" (if=Action und Abenteuer; id:id0xe2bc950 is a duplicate of if/@test="Adventure"</Genre> 
    <Genre>B-Grade</Genre> 
</Metadata> 

所以,你可以做你想做與發現重複什麼的。請注意,使用preceding-sibling::爲每個genre節點使算法O(N²)(又稱10倍更多<genre/>節點將使代碼長100倍)。

順便說一句,有一個ifs.xml來處理測試/值將使得比XSL中的原始編碼測試更具可擴展性。

+0

我建議你熟悉* Muenchian分組* - 請參閱Martin Honnen上面評論中的鏈接。 – 2014-09-22 20:39:52