12

鉴于这段 XML

<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>

我应该需要使用 XSL 仅输出不以 . 开头 info:eu-repo的字符串的年份。我正在尝试这种方式,但它不起作用。我错了for-each

<xsl:if test="not(starts-with('dc:date', 'info:eu-repo'))">
                <xsl:for-each select="dc:date">
                    <publicationYear>
                        <xsl:variable name="date" select="."/>
                        <xsl:value-of select="substring($date, 0, 5)"/>
                    </publicationYear>
                </xsl:for-each>
</xsl:if>
4

3 回答 3

23

'我猜您的查询中不需要start-with,并且您可能希望以稍微不同的方式迭代日期:

    <xsl:for-each select="dc:date">
         <xsl:variable name="date" select="."/>
         <xsl:if test="not(starts-with($date, 'info:eu-repo'))">
                <publicationYear>
                    <xsl:value-of select="substring($date, 0, 5)"/>
                </publicationYear>
        </xsl:if>
    </xsl:for-each>
于 2012-09-20T08:18:52.990 回答
2

你也可以使用 atemplate-match来得到你想要的,例如:

<xsl:template match="date[not(starts-with(.,'info:eu-repo'))]">
    <xsl:value-of select="."/>
</xsl:template>

我有这个输入 XML:

<?xml version="1.0" encoding="UTF-8"?>
<list>
<date>info:eu-repo/date/embargoEnd/2013-06-12</date>
<date>2012-07-04</date>
</list>

并将这个 XSLT 应用到它:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="text() | @*"/>

<xsl:template match="/">
    <xsl:apply-templates />
</xsl:template> 

<xsl:template match="date[not(starts-with(.,'info:eu-repo'))]">
    <xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

我得到这个输出:

<?xml version="1.0" encoding="UTF-8"?>2012-07-04
于 2012-09-20T11:14:26.430 回答
2

使用(假设提供的 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>
于 2012-09-20T11:30:00.023 回答