2016-12-04 147 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>等。使用这些常常会导致令人费解的,不易理解的意大利面代码,并且在过程/命令式和声明式/函数式编程风格中都是反模式。