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

时间:2012-04-19 17:00:52

标签: 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))。

我应该如何在今天的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>

这是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>

1 个答案:

答案 0 :(得分:1)

没有HTML输出应该是什么的例子,但我非常确定我能说出你想要实现的目标。

我认为您可以通过删除xsl:ifxsl: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>

如果这不是您要查找的内容,请添加HTML输出的示例。