xsl: если первый и последний узлы не восстановлены

#xslt #xslt-1.0

#xslt #xslt-1.0

Вопрос:

У меня есть XML следующего вида:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ExistingReservations>
    <reservations>
        <reservation>
            <type>1</type>
            <start_time>2019-03-09T16:11:14Z</start_time>
            <stop_time>2019-03-09T16:23:23Z</stop_time>
        </reservation>
        <reservation>
            <type>2</type>
            <start_time>2019-03-09T11:23:12Z</start_time>
            <stop_time>2019-03-09T11:32:18Z</stop_time>
        </reservation>
        <reservation>
            <type>2</type>
            <start_time>2019-03-09T12:23:12Z</start_time>
            <stop_time>2019-03-09T12:32:18Z</stop_time>
        </reservation>
    </reservations>
</ExistingReservations>
  

Я хочу посмотреть только на оговорки типа ‘2’, а затем получить диапазон дат. т.е. первое время начала и последнее время окончания.

Но у меня проблемы с моим xsl, поскольку, похоже, я не могу получить первую и последнюю позиции.

Мой xsl выглядит следующим образом:

 <?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="ExistingReservations">
        <ReservationSchedule>
            <xsl:for-each select="//reservation">
                <xsl:if test="type='2'">
                    <period>
                        <xsl:if test="position()=1">
                            <start_time><xsl:value-of select="start_time"/><start_time>
                        </xsl:if>

                        <xsl:if test="position() = last()">
                            <end_time><xsl:value-of select="stop_time"/></end_time>
                        </xsl:if>

                    </period>
                </xsl:if>
            </xsl:for-each>
        </ReservationSchedule>
    </xsl:template>
</xsl:stylesheet>
  

Итак, я хочу преобразовать к следующему:

 <ReservationSchedule>
    <period>
        <start_time>2019-03-09T11:23:12Z</start_time>
        <end_time>2019-03-09T12:32:18Z</end_time>
    </period>
</ReservationSchedule>
  

Я думаю, что в <xsl:if test="position()=1"> не работает, потому что он смотрит на первый узел, который имеет тип 1 .. т. Е. он использует <xsl:if test="type='2'"> логику.

Любая помощь приветствуется.

Ответ №1:

Вы xsl:for-each выбираете все резервирования, поэтому position() они будут основаны на этом выбранном наборе узлов. Это xsl:if не повлияет на position() функцию.

Что вам нужно сделать, так это изменить сам select оператор, чтобы в первую очередь выбирались только резервирования типа 2

 <xsl:template match="ExistingReservations">
    <ReservationSchedule>
        <xsl:for-each select="//reservation[type='2']">
            <period>
                <xsl:if test="position()=1">
                    <start_time><xsl:value-of select="start_time"/></start_time>
                </xsl:if>

                <xsl:if test="position() = last()">
                    <end_time><xsl:value-of select="stop_time"/></end_time>
                </xsl:if>
            </period>
        </xsl:for-each>
    </ReservationSchedule>
</xsl:template>
  

В качестве альтернативы, вы можете избавиться от xsl:for-each и записать это следующим образом:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="ExistingReservations">
        <ReservationSchedule>
            <xsl:variable name="type2s" select="//reservation[type='2']" />
            <period>
                <start_time><xsl:value-of select="$type2s[1]/start_time"/></start_time>
                <end_time><xsl:value-of select="$type2s[last()]/stop_time"/></end_time>
            </period>
        </ReservationSchedule>
    </xsl:template>
</xsl:stylesheet>
  

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

1. Ах да, конечно. Я думаю, это должен быть какой-то простой Xpath. <xsl: для каждого select=»//резервирование[тип=’2′]»> СПАСИБО!!