XSLT选择采取哪些子元素
我有这个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>
任何帮助解决这将是有益的比较。
您可以使用xsl:apply-templates
或xsl: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>
好的尝试,但有一个问题。如果“type”属性的值可以是另一个值的子字符串,这将产生错误的结果。提示:分隔必须在*两边*和两个参数上。另外,没有必要使用'string-length()' –
@DimitreNovatchev我知道子字符串的问题,但是假设OP有一些离散的非重叠值。我现在已经修复了这个问题,现在我看到为什么不需要字符串长度。谢谢你让我的脚趾头。 – JLRishe
JLRishe,不客气! –
如果你想从不同的日期中选择,你必须从父母的上下文中选择。在给出的例子中,它可能看起来像这样:
<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>
至于因为这简单 - 注意,您不需要使用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>
等。使用这些常常会导致令人费解的,不易理解的意大利面代码,并且在过程/命令式和声明式/函数式编程风格中都是反模式。
请注明是否使用XSLT 1.0或2.0。 –