使用方法(假设提供的XML片段是当前节点的子元素,并且只有一个具有所需属性的元素):
substring-before(*[not(starts-with(., 'info:eu-repo'))], '-')
XSLT基于验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy-of select=
"substring-before(*[not(starts-with(., 'info:eu-repo'))], '-') "/>
</xsl:template>
</xsl:stylesheet>
当将此变换应用于以下XML文档时(提供的片段包装在单个顶部元素中并声明命名空间):
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
</t>
XPath表达式是基于顶级元素进行评估的,此评估的结果将被复制到输出中。
2012
II. 拥有所需属性的元素不止一个:
在这种情况下,使用单个XPath 1.0表达式无法产生所需的数据。
以下是XSLT转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(starts-with(., 'info:eu-repo'))]/text()">
<xsl:copy-of select="substring-before(., '-') "/>
==============
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
应用于此XML文档时:
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2011-07-05</dc:date>
</t>
产生所需的、正确的结果:
2012
==============
2011
==============
III. XPath 2.0 单行代码
*[not(starts-with(., 'info:eu-repo'))]/substring-before(., '-')
当对最后一个XML文档(最接近顶部的元素)执行此XPath 2.0表达式时,所需的年份将被生成:
2012 2011
XSLT 2.0 基于验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:sequence select=
"*[not(starts-with(., 'info:eu-repo'))]/substring-before(., '-')"/>
</xsl:template>
</xsl:stylesheet>
当将此转换应用于最后一个XML文档时,XPath表达式将被评估,并将此评估的结果复制到输出中:
2012 2011
IV. 最一般和最困难的情况:
现在,让我们看看这个XML文档:
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2011-07-05</dc:date>
<dc:date>*/date/embargoEnd/2014-06-12</dc:date>
</t>
我们仍然希望获取所有
dc:date
元素的年份部分,但其字符串值不以'info:eu-repo'开头。然而,之前的解决方案都不能正确处理上面最后一个
dc:date
元素。
值得注意的是,可以通过单个XPath 2.0表达式仍然产生所需的数据:
for $s in
*[not(starts-with(., 'info:eu-repo'))]/tokenize(.,'/')[last()]
return
substring-before($s, '-')
当对上述XML文档的顶部元素进行表达式求值时,将产生所需的正确结果:
2012 2011 2014
以下是基于XSLT 2.0的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:sequence select=
"for $s in
*[not(starts-with(., 'info:eu-repo'))]/tokenize(.,'/')[last()]
return
substring-before($s, '-')
"/>
</xsl:template>
</xsl:stylesheet>
<xsl:for-each select="dc:date[not(starts-with(., 'info:eu-repo'))]">
。 - Tim C