XSL if测试以starts-with开始

13

给定这段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>
3个回答

25

我猜你在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>

3
请注意,您可以将条件xsl:ifxsl:for-each本身相结合,以简化操作... <xsl:for-each select="dc:date[not(starts-with(., 'info:eu-repo'))]"> - Tim C

2
你可以使用 template-match 来获取你想要的内容,例如:
<xsl:template match="date[not(starts-with(.,'info:eu-repo'))]">
    <xsl:value-of select="."/>
</xsl:template>

I have this input 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

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

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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接