XSLT:如何测试是否至少存在一个合格的子节点/@date

XSLT:如何测试是否至少存在一个合格的子节点/@date,xslt,compare,Xslt,Compare,我想测试一个组中同时符合city和current-date()条件的事件,以便输出标题 找到城市($place eq//event/@city)似乎很有效。但我不知道如何表达“一些eventTime/@date今天低于$today”。错误消息是“不允许一个以上项目的序列作为'eq'的第二个操作数”,这令人困惑,因为我已经编写了test=“($place eq//event/@city)和(xs:date($today)lt xs:date(//eventTime/@date)) 我应该如何将$t

我想测试一个组中同时符合city和current-date()条件的事件,以便输出标题

找到城市($place eq//event/@city)似乎很有效。但我不知道如何表达“一些eventTime/@date今天低于$today”。错误消息是“不允许一个以上项目的序列作为'eq'的第二个操作数”,这令人困惑,因为我已经编写了test=“($place eq//event/@city)和(xs:date($today)lt xs:date(//eventTime/@date))

我应该如何将$today与eventTime中的@date进行比较?以下是输入

<calendar>  
<group month="2012-04-01">
    <event city="paris">
        <eventTime date="2012-04-02"/>
        <eventText>Paris - expired April date</eventText>
    </event>
    <event city="london">
        <eventTime date="2012-04-19"/>
        <eventText>London - current April 19 date</eventText>
    </event>
    <event city="london">
        <eventTime date="2012-04-24"/>
        <eventText>London - current April date</eventText>
    </event>
</group>
<group month="2012-05-01">
    <event city="london">
        <eventTime date="2012-05-02"/>
        <eventText>London - current May date</eventText>
    </event>
    <event city="paris">
        <eventTime date="2012-05-01"/>
        <eventText>Paris - current May date</eventText>
    </event>
    <event city="london">
        <eventTime date="2012-05-02"/>
        <eventText>London - current May date</eventText>
    </event>
</group>

</calendar>

巴黎-4月到期
伦敦-当前日期为4月19日
伦敦-当前四月日期
伦敦-当前五月日期
巴黎-当前五月日期
伦敦-当前五月日期
以下是XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://johnadamturnbull.com/xslt"
                exclude-result-prefixes="xs"
                version="2.0" >

    <xsl:output method="html" indent="yes" name="html"/>

    <xsl:param name="place" as="xs:string" required="yes"></xsl:param>
    <xsl:variable name="today" select="current-date()" as="xs:date"/>

      <xsl:template match="/">
        <html>
           <body>
         <xsl:apply-templates select="calendar/group"/>
        </body>
        </html>  
    </xsl:template>



    <xsl:template match = "group">

        <xsl:if test="($place eq //event/@city) and
               (xs:date($today) ge xs:date(//eventTime/@date))">

              <h4 class = "dateHeader">
                    <xsl:value-of select="format-date(./@month,'[MNn] [Y]')"/>
                </h4>
                <ul>
                    <xsl:apply-templates select="event"></xsl:apply-templates>
                </ul>
        </xsl:if>
    </xsl:template>

    <xsl:template match="event">
       <xsl:variable name="eventTime" select="eventTime/@date" as="xs:date"/>
        <xsl:choose>
            <xsl:when test="($eventTime ge $today) and
                            (($place eq @city) or (@city eq ''))">
                <li>
                        <xsl:apply-templates></xsl:apply-templates>
                </li>
            </xsl:when>
            </xsl:choose>
    </xsl:template>

</xsl:stylesheet>


  • 没有一个HTML输出应该是什么的示例,但是我非常确定我可以告诉您要实现什么

    我认为可以通过删除
    xsl:if
    xsl:choose
    并添加谓词来进行测试来简化XSLT

    此XSLT 2.0样式表:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:fn="http://johnadamturnbull.com/xslt" exclude-result-prefixes="xs fn" version="2.0">
      <xsl:output method="html" indent="yes" name="html"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:param name="place" as="xs:string" required="yes"/>
      <xsl:variable name="today" select="current-date()" as="xs:date"/>
    
      <xsl:template match="/">
        <html>
          <body>
            <xsl:apply-templates select="calendar/group"/>
          </body>
        </html>
      </xsl:template>
    
      <!--Match group if @city matches $place or is empty and has an eventTime
      with a @date that is greater than or equal to today's date.-->
      <xsl:template match="group[event[@city=$place or @city=''][xs:date(eventTime/@date) >= $today]]">
          <h4 class="dateHeader">
            <xsl:value-of select="format-date(@month,'[MNn] [Y]')"/>
          </h4>
          <ul>
            <!--Only apply-templates to events that have a @city that matches $place
            or has a @city that is empty.-->
            <xsl:apply-templates select="event[@city=$place or @city='']"/>
          </ul>
      </xsl:template>
    
      <!--Only match events that have an eventTime with a @date that is greater than 
      or equal to today's date.-->
      <xsl:template match="event[@city=$place or @city=''][xs:date(eventTime/@date) >= $today]">
        <li>
          <xsl:apply-templates/>
        </li>
      </xsl:template>
    
      <xsl:template match="event"/>
    
    </xsl:stylesheet>
    
    
    
  • 应用于示例XML输入将生成以下HTML输出:

    <html>
       <body>
          <h4 class="dateHeader">April 2012</h4>
          <ul>
             <li>London - current April 19 date</li>
             <li>London - current April date</li>
          </ul>
          <h4 class="dateHeader">May 2012</h4>
          <ul>
             <li>London - current May date</li>
             <li>London - current May date</li>
          </ul>
       </body>
    </html>
    
    
    2012年4月
    
    • 伦敦-当前日期为4月19日
    • 伦敦-当前四月日期
    2012年5月
    • 伦敦-当前五月日期
    • 伦敦-当前五月日期

    如果这不是您想要的,请添加一个HTML输出应该是什么样子的示例。

    //event/@city
    将返回一个由6项组成的序列。您可以发布XSLT以便我们可以看到您试图实现的目标吗?我说的是“少于今天”--我的意思是>=今天。这正是我需要的输出。它适用于“伦敦”但是当我传入place参数“Paris”时,它失败了。(我得到的结果是…巴黎-过期的4月日期伦敦-当前的4月19日日期@JohnTurnbull-对此表示抱歉。我需要在事件匹配中添加$place谓词,并且我需要添加另一个事件匹配以捕捉迷路。请查看我的编辑。这太棒了!我现在正在获取谓词。非常感谢您--这真是太棒了。)有用。我正要放弃XSLT,在XQuery中这样做。你也写XQuery;你会用它来代替吗?@JohnTurnbull-不客气。不,我仍然会在XSLT中这样做,但我在XSLT中也会更自如。这里的关键是知道如何使用XPath。如果我在XQuery中这样做,我可能仍然会使用相同的XPath(使用谓词)。