XSLT: возврат результатов на основе следующего значения родственного элемента

Я новичок в XSLT. Любая помощь будет оценена ....

<Test>
  <loop loop_id="5" LoopElementOrder_no="1" Segment_id="3" >
     <usage_id>1</usage_id>
    <value>41</value>
  </loop>
  <loop loop_id="5" LoopElementOrder_no="2"  Segment_id="3">
    <usage_id>1</usage_id>
     <value>2</value>
      </loop>
  <loop loop_id="5" LoopElementOrder_no="4" Segment_id="3">
     <usage_id>2</usage_id>
     <value>raj</value>
      </loop>
  <loop loop_id="5" LoopElementOrder_no="5" Segment_id="3">
     <usage_id>3</usage_id>
      <value>d</value>
    </loop>
  <loop loop_id="5"  LoopElementOrder_no="6" Segment_id="3">
    <usage_id>3</usage_id>  
      <value>8</value>
  </loop>
  <loop loop_id="5"  LoopElementOrder_no="7" Segment_id="3">
    <usage_id>3</usage_id>
      <value>7</value>
  </loop>
  <loop loop_id="5" LoopElementOrder_no="1" Segment_id="4">
       <usage_id>1</usage_id>

    <value>IC</value>
      </loop>
  <loop loop_id="5"  LoopElementOrder_no="2" Segment_id="4">
  <usage_id>2</usage_id>
      <value>d</value> 
  </loop>
 <loop loop_id="5"  LoopElementOrder_no="3" Segment_id="4">
      <usage_id>3</usage_id>
          <value>dm</value> 
      </loop> 
 <loop loop_id="5"  LoopElementOrder_no="4" Segment_id="4">
      <usage_id>2</usage_id>
          <value>wj</value> 
      </loop> 
    </Test>

Я хотел бы вернуть «значение», только если его использование_id равно 1 или 2. В случае, если использование_идентификатор равно 3, оно должно вернуть «Н/Д». Однако, например, если я в Segment_id=3 LoopElementOrder_no=5, то оставшаяся часть Segment_id=3 не содержит Usage_id как 1 или 2, и в этом случае мне нужно вернуть «^» и продолжить его с Segment_id=4 с LoopElementOrder_no =1.

Желаемый результат для вышеизложенного:

41 2 raj ^IC d N/A wj

person user2251759    schedule 06.04.2013    source источник
comment
Можете ли вы показать образец ожидаемого результата в этом случае? Спасибо!   -  person Tim C    schedule 06.04.2013
comment
Спасибо, Тим. Вот вывод, аналогичный приведенному выше случаю 41 2 raj ^IC d   -  person user2251759    schedule 06.04.2013
comment
Итак, не могли бы вы показать нам пример ввода, который приведет к тому, что на выходе будет N/A?   -  person JLRishe    schedule 06.04.2013


Ответы (2)


Короткое, простое (всего три шаблона, без xsl:apply-templates, без xsl:variable, без current() и без режимов) и более понятное решение, выполненное полностью в стиле "push":

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="loop[not(usage_id >2)]">
  <xsl:value-of select="concat(value, ' ')"/>
 </xsl:template>

 <xsl:template match=
 "loop[usage_id = 3
     and preceding-sibling::loop[not(usage_id >2)][1]/@Segment_id
        =following-sibling::loop[not(usage_id >2)][1]/@Segment_id
      ]
 ">N/A </xsl:template>

 <xsl:template match=
 "loop
   [usage_id >2
  and
    preceding-sibling::loop[1][not(usage_id >2)]
  and
    not(@Segment_id =following-sibling::loop[not(usage_id >2)][1]/@Segment_id)
    ]">^ </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному XML-документу:

<Test>
  <loop loop_id="5" LoopElementOrder_no="1" Segment_id="3" >
     <usage_id>1</usage_id>
    <value>41</value>
  </loop>
  <loop loop_id="5" LoopElementOrder_no="2"  Segment_id="3">
    <usage_id>1</usage_id>
     <value>2</value>
      </loop>
  <loop loop_id="5" LoopElementOrder_no="4" Segment_id="3">
     <usage_id>2</usage_id>
     <value>raj</value>
      </loop>
  <loop loop_id="5" LoopElementOrder_no="5" Segment_id="3">
     <usage_id>3</usage_id>
      <value>d</value>
    </loop>
  <loop loop_id="5"  LoopElementOrder_no="6" Segment_id="3">
    <usage_id>3</usage_id>
      <value>8</value>
  </loop>
  <loop loop_id="5"  LoopElementOrder_no="7" Segment_id="3">
    <usage_id>3</usage_id>
      <value>7</value>
  </loop>
  <loop loop_id="5" LoopElementOrder_no="1" Segment_id="4">
       <usage_id>1</usage_id>

    <value>IC</value>
      </loop>
  <loop loop_id="5"  LoopElementOrder_no="2" Segment_id="4">
  <usage_id>2</usage_id>
      <value>d</value>
  </loop>
 <loop loop_id="5"  LoopElementOrder_no="3" Segment_id="4">
      <usage_id>3</usage_id>
          <value>dm</value>
      </loop>
 <loop loop_id="5"  LoopElementOrder_no="4" Segment_id="4">
      <usage_id>2</usage_id>
          <value>wj</value>
      </loop>
</Test>

получен желаемый правильный результат:

41 2 raj ^ IC d N/A wj

Обновление:

Решение можно еще сократить и упростить:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="loop[not(usage_id >2)]">
   <xsl:if test=
   "preceding-sibling::loop[not(usage_id >2)][1]
      [not(@Segment_id = current()/@Segment_id)]">^ </xsl:if>
   <xsl:value-of select="concat(value, ' ')"/>
 </xsl:template>

 <xsl:template match=
 "loop[usage_id = 3
     and preceding-sibling::loop[not(usage_id >2)][1]/@Segment_id
        =following-sibling::loop[not(usage_id >2)][1]/@Segment_id
      ]
 ">N/A </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>
person Dimitre Novatchev    schedule 06.04.2013

Пожалуйста, попробуйте это:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="loop">
    <xsl:value-of select="concat(value, ' ')"/>
  </xsl:template>

  <xsl:template match="loop[usage_id = 3]">
    <xsl:variable name="segmentId" select="@Segment_id" />
    <xsl:variable name="following12"
                  select="following-sibling::loop[@Segment_id = $segmentId]
                                                 [usage_id = 1 or usage_id = 2]" />
    <xsl:apply-templates
      select="current()[not(preceding-sibling::loop[1]
                                                   [@Segment_id = $segmentId]
                                                   [usage_id = 3])
                        and not($following12)]" mode="carat" />
    <xsl:apply-templates select="current()[$following12]" mode="na" />
  </xsl:template>

  <xsl:template match="loop" mode="na">
    <xsl:text>N/A </xsl:text>
  </xsl:template>

  <xsl:template match="loop" mode="carat">
    <xsl:text>^</xsl:text>
  </xsl:template>
</xsl:stylesheet>

При запуске на вашем образце ввода результат будет следующим:

41 2 raj ^IC d N/A wj 
person JLRishe    schedule 06.04.2013