使用(假设提供的 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
二、具有所需属性的多个元素:
在这种情况下,不可能使用单个 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
==============
三、XPath 2.0 单行
*[not(starts-with(., 'info:eu-repo'))]/substring-before(., '-')
当这个 XPath 2.0 表达式从最后一个 XML 文档的顶部元素(上面最近的)进行评估时,就会产生所需的年份:
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
四。最普遍和最困难的情况:
现在,让我们拥有这个 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>