XSL如果测试开始 - 用

时间:2012-09-20 08:15:14

标签: xslt xpath xpath-2.0

鉴于这段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 个答案:

答案 0 :(得分:19)

我猜您在'查询中不需要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>

答案 1 :(得分:1)

您还可以使用template-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

祝你好运, 彼得

答案 2 :(得分:1)

使用(假设提供的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>

我们仍希望获得其字符串值不以'info:eu-repo'开头的所有dc:date元素的年份部分。但是,以前的解决方案都不能正常使用上面的最后一个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>