Получить значение следующего существующего элемента после сортировки

#xml #xslt

#xml — файл #в XSLT #xml #xslt

Вопрос:

У меня есть это xml :

 <ns4:Dmpp ProductId="oLRbYoE VfG=" deliveryEnvironment="P" code="1482223" codeType="CNK">
   <ns4:Data from="2020-03-01">
      <Reimbursable>false</Reimbursable>
   </ns4:Data>
   <ns4:Data from="2012-06-01" to="2016-07-14">
      <Price>6.3100</Price>
      <Reimbursable>false</Reimbursable>
   </ns4:Data>
   <ns4:Data from="2016-07-15" to="2019-12-11">
      <Reimbursable>false</Reimbursable>
   </ns4:Data>
      <ns4:Data from="2019-12-12" to="2020-02-29">
      <Price>7.5000</Price>
      <Reimbursable>true</Reimbursable>
   </ns4:Data>
</ns4:Dmpp>
  

С помощью этого xsl

 <xsl:for-each select="ns4:Dmpp">
      <xsl:text>INSERT INTO DMPPACKAGING VALUES ('</xsl:text>
      <xsl:value-of select="@ProductId" />
      <xsl:text>','</xsl:text>
      <xsl:value-of select="@deliveryEnvironment" />
      <xsl:text>','</xsl:text>
      <xsl:for-each select="ns4:Data">
        <xsl:sort select="translate(@from,'-','')" order="descending" data-type="number" />
        <xsl:if test="position() = 1">
          <xsl:value-of select="@from" />
          <xsl:text>','</xsl:text>
          <xsl:choose>
            <xsl:when test="@to !=''">
              <xsl:value-of select="@to"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="'0000-00-00'" />
            </xsl:otherwise>
          </xsl:choose>
          <xsl:text>','</xsl:text>
          <xsl:value-of select="../@codeType" />
          <xsl:text>','</xsl:text>
          <xsl:value-of select="../@code" />
          <xsl:text>','</xsl:text>
          <xsl:value-of select="Reimbursable" />
          <xsl:text>','</xsl:text>
          <xsl:choose>
            <xsl:when test="Price !=''">
              <xsl:value-of select="Price"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="../ns4:Data/following-sibling::ns4:Data/Price" />
            </xsl:otherwise>
          </xsl:choose>
        </xsl:if>
      </xsl:for-each>
      <xsl:text>');</xsl:text>
    </xsl:for-each>
  

Как вы можете видеть в этом примере, Position() = 1 дайте мне только данные <Reimbursable> элемента.

Я хотел бы получить более свежую информацию о цене продукта. С моим кодом я получаю его, только если это второй элемент отсортированного элемента, но это не всегда так.

Любая помощь будет оценена по достоинству !

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

1. Если вам нужна самая последняя цена, то сортируйте только те узлы, у которых есть цена.

2. Не уверен, что я действительно понимаю, что вы хотите, но если вам нужна последняя цена, вы могли бы изменить свое последнее значение выбора на <xsl:значение выбора=»../ns4:Данные / следующие-sibling::ns4:Data[position()=last()]/Price»/>

3. @michael.hor257k Мне нужны данные из самого последнего Reimbursable элемента и данные из самого последнего Price элемента. Иногда Reimbursable и Price находятся в одном и том же ns4:Data элементе, но иногда нет. Итак, в этом примере мне нужно <Reimbursable>false</Reimbursable> из <ns4:Data from="2020-03-01"> и <Price>7.5000</Price> из <ns4:Data from="2019-12-12" to="2020-02-29">

4. Тогда я предлагаю вам сначала отсортировать узлы, у которых есть Reimbursable элемент, и получить первый из них, затем отсортировать узлы, у которых есть Price элемент, и получить первый из них. В противном случае вам пришлось бы поместить отсортированные узлы в переменную, преобразовать переменную в набор узлов (предполагая XSLT 1.0), а затем искать первый узел, у которого есть Reimbursable элемент, и — отдельно — первый узел, у которого есть Price элемент. Намного сложнее.

Ответ №1:

На самом деле, мое предложение состояло в том, чтобы сделать:

 <xsl:text>MOST RECENT REIMBURSABLE: </xsl:text>
<xsl:for-each select="ns4:Data[Reimbursable]">
    <xsl:sort select="@from" order="descending" />
    <xsl:if test="position() = 1">
        <xsl:value-of select="@from"/>
    </xsl:if>
</xsl:for-each>
<xsl:text> MOST RECENT PRICE: </xsl:text>
<xsl:for-each select="ns4:Data[Price]">
    <xsl:sort select="@from" order="descending" />
    <xsl:if test="position() = 1">
        <xsl:value-of select="@from"/>
    </xsl:if>
</xsl:for-each>
  

Ответ №2:

Вот как я решил свою проблему с помощью предложения @michael.hor257k :

Я только помещу код внутрь, <xsl:choose> где мне нужно получить более свежий Price элемент.

 <xsl:choose>
   <xsl:when test="Price !=''">
      <xsl:value-of select="Price"/>
   </xsl:when>
   <xsl:otherwise>            
      <xsl:for-each select="../ns4:Data/Price">
         <xsl:sort select="translate(../@from,'-','')" order="descending" data-type="number" />
         <xsl:if test="position() = 1">
            <xsl:value-of select="." />
         </xsl:if>
      </xsl:for-each>
   </xsl:otherwise>
</xsl:choose>