2016-12-04 145 views
1

我有這個MODSXSLT選擇採取哪些子元素

<modsCollection> 
    <mods ID="master"> 
    <originInfo> 
     <dateOther encoding="8601" type="publication">2016</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="onlineFirst">2015</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="accepted">2014</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="submitted">2013</dateOther> 
    </originInfo> 
    </mods> 
</modsCollection> 

我需要將這一元素dateOther爲等效DC:日期,但我有不同的類型屬性,只需要一dateOther(如果一個刊物存在,我們採取這個日期,否則,如果它不比我們在線第一,如果它不存在,接受等)。

所以在上MODS的情況下,我們將創建

<dc:date>2016</dc:date> 

因爲屬性類型=出版物dateOther存在,如果沒有,我們將採取類型= onlineFirst等

日期的順序其他外觀可能不同,只能有一個或多個。

問題開始轉變,我無法選擇所有originInfo/dateOther元素,所以我可以通過選擇

<xsl:template match="//mods:mods[@ID = 'master']/mods:originInfo/mods:dateOther"> 
    <xsl:choose> 
    <xsl:when test="..."> 

     <dc:date>...</dc:date> 

    </xsl:when> 
    ... 
    </xsl:choose> 
</xsl:template> 

任何幫助解決這將是有益的比較。

+0

請註明是否使用XSLT 1.0或2.0。 –

回答

0

您可以使用xsl:apply-templatesxsl:for-each將它們排序爲正確的優先級,然後選擇第一個(注意:您沒有告訴我們您正在使用的命名空間,所以我沒有使用任何命名空間在我的例子中):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="mods[@ID = 'master']"> 
    <xsl:apply-templates select="originInfo/dateOther"> 
     <xsl:sort select="substring-before(
          '|publication|onlineFirst|accepted|submitted|', 
          concat('|', @type, '|') 
         )" /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="dateOther"> 
     <xsl:if test="position() = 1"> 
     <date><xsl:value-of select="." /></date> 
     </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 
+0

好的嘗試,但有一個問題。如果「type」屬性的值可以是另一個值的子字符串,這將產生錯誤的結果。提示:分隔必須在*兩邊*和兩個參數上。另外,沒有必要使用'string-length()' –

+1

@DimitreNovatchev我知道子字符串的問題,但是假設OP有一些離散的非重疊值。我現在已經修復了這個問題,現在我看到爲什麼不需要字符串長度。謝謝你讓我的腳趾頭。 – JLRishe

+0

JLRishe,不客氣! –

-1

如果你想從不同的日期中選擇,你必須從父母的上下文中選擇。在給出的例子中,它可能看起來像這樣:

<xsl:template match="mods[@ID = 'master']"> 
    <!-- other stuff? --> 
    <date> 
     <xsl:choose> 
      <xsl:when test="originInfo/dateOther[@type='publication']"> 
       <xsl:value-of select="originInfo/dateOther[@type='publication']"/> 
      </xsl:when> 
      <xsl:when test="originInfo/dateOther[@type='onlineFirst']"> 
       <xsl:value-of select="originInfo/dateOther[@type='onlineFirst']"/> 
      </xsl:when> 
      <xsl:when test="originInfo/dateOther[@type='accepted']"> 
       <xsl:value-of select="originInfo/dateOther[@type='accepted']"/> 
      </xsl:when> 
      <!-- and so on --> 
     </xsl:choose> 
    </date> 
    <!-- more stuff? --> 
</xsl:template> 

這是假定XSLT 1.0。有在XSLT 2.0附加選項 - 例如:

<xsl:template match="mods[@ID = 'master']"> 
    <!-- other stuff? --> 
    <date> 
     <xsl:value-of select="(originInfo/dateOther[@type='publication'], originInfo/dateOther[@type='onlineFirst'], originInfo/dateOther[@type='accepted'], originInfo/dateOther[@type='submitted'])[1]"/> 
    </date> 
    <!-- more stuff? --> 
</xsl:template> 
0

至於因爲這簡單 - 注意,您不需要使用string-length()功能:

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

<xsl:variable name="vTypes" select="'|publication|onlineFirst|accepted|submitted|'"/> 

    <xsl:template match="mods"> 
    <dc:date> 
     <xsl:for-each select="originInfo/dateOther"> 
     <xsl:sort select="substring-before($vTypes, concat('|', @type, '|'))"/> 
     <xsl:variable name="vPos" select="position()"/> 
     <xsl:value-of select="self::node()[$vPos=1]"/> 
     </xsl:for-each> 
    </dc:date> 
    </xsl:template> 
</xsl:stylesheet> 

當這一轉變施加在下面的XML文檔(所提供的一個,但是元素混洗,使得結果不是在頂部):

<modsCollection> 
    <mods ID="master"> 
    <originInfo> 
     <dateOther encoding="8601" type="onlineFirst">2015</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="accepted">2014</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="publication">2016</dateOther> 
    </originInfo> 
    <originInfo> 
     <dateOther encoding="8601" type="submitted">2013</dateOther> 
    </originInfo> 
    </mods> 
</modsCollection> 

想要的,正確的結果產生

<dc:date xmlns:dc="my:dc">2016</dc:date> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:dc="my:dc"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:variable name="vTypes" select="'publication','onlineFirst','accepted','submitted'"/> 


    <xsl:template match="mods"> 
    <dc:date> 
     <xsl:sequence select= 
     "*/*[index-of($vTypes,@type)[1] 
      eq min(current()/*/*/index-of($vTypes,@type)[1])]/text()"/> 
    </dc:date> 
    </xsl:template> 
</xsl:stylesheet> 

注意

我強烈建議儘量避免使用XSLT條件指示器如<xsl:if>,<xsl:choose>,<xsl:when>等。使用這些常常會導致令人費解的,不易理解的意大利麪代碼,並且在過程/命令式和聲明式/函數式編程風格中都是反模式。