Как мне отобразить ограниченное количество элементов в XSLT?

#xslt

#xslt

Вопрос:

Мне нужно отобразить указанное количество элементов из источника XML, где значение элементов «DueDate» не указано. Вот пример xml:

 <Items>
  <Item>
    <Title>Title 1</Title>
    <DueDate>01-02-2008</DueDate>
  </Item>
  <Item>
    <Title>Title 2</Title>
    <DueDate>01-02-2009</DueDate>
  </Item>
  <Item>
    <Title>Title 3</Title>
    <DueDate>01-02-2010</DueDate>
  </Item>
  <Item>
    <Title>Title 4</Title>
    <DueDate>01-02-2011</DueDate>
  </Item>
  <Item>
    <Title>Title 5</Title>
    <DueDate>01-02-2012</DueDate>
  </Item>
  <Item>
    <Title>Title 6</Title>
    <DueDate>01-02-2013</DueDate>
  </Item>
</Items>
  

Количество отображаемых элементов и текущая дата передаются в XSLT в качестве параметров.
Можно ли подсчитать количество отображаемых элементов в цикле for-each в Xslt? Или есть подход получше?

Примером может быть то, что ограничение было установлено на 3 элемента. В этом примере я ожидал бы увидеть следующие результаты: «Заголовок 3», «Заголовок 4» и «Заголовок 5».

Ответ №1:

Вы можете сделать что-то вроде этого. Превратите это в шаблон, который вы можете вызывать с параметрами:

 <xsl:template match="/">
<xsl:variable name="count" select="3"/>

<xsl:for-each select="Items/Item">
    <xsl:if test="position() amp;< $count">
        <xsl:value-of select="Title"/> - <xsl:value-of select="DueDate"/>
    </xsl:if>
</xsl:for-each>
  

Комментарии:

1. Но это не приведет к удалению элементов, у которых «DueDate» больше, чем сегодня? Это просто даст мне первые три элемента! Если я включу оператор if для проверки даты, будет показан только третий (position() == 3) «допустимый» элемент.

Ответ №2:

Попробуйте вложить это в стандартный xsl for-each, где n в вашем случае равно 3:

 <xsl:if test="position() amp;< n">
  

Но если вы также хотите проверить дату, то вам нужно вложить другое if и создать даты в формате ггггММдд, которые можно сравнить численно следующим образом:

 <xsl:variable name="secondDate" select="concat(substring(submissionDeadline, 1,4),substring(submissionDeadline, 6,2),substring(submissionDeadline, 9,2))"/>

<xsl:if test="$firstDate amp;> $secondDate">
  

Ответ №3:

Основная проблема заключается в том, что ваш входной XML-файл не соответствует полезному формату ‘гггг-мм-дд’. Это затрудняет сортировку / фильтрацию этих элементов в Жопа позади.

Если я вас правильно понял, вам необходимо

  • сначала отфильтруйте по сроку выполнения
  • после этого примените максимум к выходным данным

XPath для выбора всех <Item> до определенного максимального срока выполнения будет выглядеть следующим образом:

 Item[
  substring-before(DueDate, '-') 
  amp;<= 
  substring-before($MaxDueDate, '-')

  and

  substring-before(substring-after(DueDate, '-'), '-')
  amp;<= 
  substring-before(substring-after($MaxDueDate, '-'), '-')

  and 

  substring-after(substring-after(DueDate, '-'), '-')
  amp;<= 
  substring-after(substring-after($MaxDueDate, '-'), '-')
][
  position() amp;<= $MaxCount
]
  

Теперь сравните это с тривиальным способом, если бы у вас были даты ‘гггг-мм-дд’:

 Item[
  DueDate amp;<= $MaxDueDate
][
  position() amp;<= $MaxCount
]
  

Итак, чтобы скопировать только эти элементы, вы должны перейти:

 <xsl:template match="Items">
  <xsl:copy>
    <xsl:copy-of select="
      { the expression I gave above }
    " />
  </xsl:copy>
</xsl:template>
  

Для значений параметров '01-02-2012' и 4 , соответственно, я получаю:

 <Items>
  <Item>
    <Title>Title 1</Title>
    <DueDate>01-02-2008</DueDate>
  </Item>
  <Item>
    <Title>Title 2</Title>
    <DueDate>01-02-2009</DueDate>
  </Item>
  <Item>
    <Title>Title 3</Title>
    <DueDate>01-02-2010</DueDate>
  </Item>
  <Item>
    <Title>Title 4</Title>
    <DueDate>01-02-2011</DueDate>
  </Item>
</Items>