Чтобы моя внешняя петля была осведомлена о существовании внутренней петли - PullRequest
2 голосов
/ 25 февраля 2011

Я думаю, что мой заголовок в основном описывает то, что я застрял в XSLT. Но если быть более точным, то, что я имею в виду, это «Как заставить внешний цикл знать, что внутренний DOES выполняется или нет в XSLT». Пожалуйста, простите меня, так как я новичок в этой области.

Во-первых, мой исходный xml является пустым, и мой XSLT в основном собирает данные из множества файлов данных xml и создает результирующий файл xml с нужными мне тегами. В частности, проблемы, с которыми я сталкиваюсь, возникают в двух шаблонах: «Наружный» и «Внутренний», и эти два шаблона фактически представляют собой структуру цикла, они пытаются циклически проходить по каждой строке определенных XML-файлов. Управление потоком прямо: я вызываю Outer в своем основном XSLT, а затем мы вводим цикл Outer для каждого элемента, и в каждом запуске этого Outer я буду называть Inner, так что это цикл структура с петлей.

На данный момент мы можем игнорировать все остальные вещи, но знаем только, что, как только я войду во внешний цикл, я создам сегмент «HL», а затем вызывается Inner и входит во внутренний цикл, и для каждого запуска Inner, Я тоже создам сегмент "HL". Следует отметить, что Inner не может быть введен, если не выполнены определенные критерии, поэтому могут быть ситуации, когда Inner вообще не вводится, и весь сегмент HL создается только в Outer.

Именно этот сегмент HL я хочу сосчитать, я поделюсь небольшим фрагментом кода, чтобы дать вам представление.

Внешний цикл:

<xsl:template name="Outer">
  <xsl:for-each select="$rechca//d_claim_rechca_export_xml_row">
    <xsl:variable name="rechca_claim_no" select=claim_number/>
       <HL01>
         <xsl:if test="$indicator=0">                                    

              <xsl:value-of select="position()+1>
          </xsl:if>
       </HL01>
    ....

  <xsl:for-each select="$rechcf//d_claim_rechcf_export_xml_row">
   <xsl:if test="claim_number=$rechca_claim_number">
     <xsl:call-template name="Inner">
      <xsl:with-param name="HLcounter" select="position()+1"/>
      </xsl:call-template>
   </xsl:if> 
  </xsl:for-each>

 </xsl:for-each> 
</xsl:template>

Внутренний цикл:

  <xsl:for-each select="$rechcf//d_claim_rechcf_export_xml_row[claim_number =$claimno and sequence_number = 1]">
 <Inner>
 <HL>
   <HL01>  
      <xsl:number value ="position()+$Hcount"/>
    </HL01>
    ....

В настоящее время в $ rechca есть две строки, и только одна в $ rechcf удовлетворяет двум циклам, поэтому внешний цикл повторяется два раза, а Inner просто выполняется один раз. Следовательно, желаемый результат должен быть

<Outer>  
  <HL>
    <HL01>2</HL01>
  </HL>
     <Inner>
         <HL01>3</HL01>     
     </Inner>
  <HL>
    <HL01>4</HL01>
  </HL>
 </Outer>

Но текущий вывод:

 <Outer>  
  <HL>
    <HL01>2</HL01>
  </HL>
     <Inner>
         <HL01>3</HL01>     
     </Inner>
  <HL>
    <HL01>3</HL01>
  </HL>
 </Outer>

Если этого внутреннего цикла нет, все будет идеально. Но в настоящее время внешний цикл не знает о существовании внутреннего цикла: после вызова внутреннего объекта, когда он возвращает управление внешнему циклу, в верхней части не должно быть «position () + 1», а «position» ( ) +2 "вместо этого (поскольку Inner был вызван один раз перед входом в этот новый Outer, поэтому там был создан новый сегмент HL). Как видите, я создал переменную под названием «индикатор». В Java / C ++ я просто обновлял бы этот индикатор на другое значение, отличное от 0, каждый раз, когда мы вводим inner, устанавливаем его в единицу. Затем выполните тест на HL01 Outer, чтобы определить правильное значение, которое будет добавлено к position ().

Действительно застрял здесь, пожалуйста, помогите! Спасибо.

1 Ответ

1 голос
/ 25 февраля 2011

Самым простым решением, не требующим объяснения различий между императивной и декларативной парадигмой, является двухфазное преобразование. Эта таблица стилей:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:template match="/">
        <xsl:variable name="vRTF-FirstPass">
            <Outer>
                <HL>
                    <HL01/>
                </HL>
                <Inner>
                    <HL01/>
                </Inner>
                <HL>
                    <HL01/>
                </HL>
            </Outer>
        </xsl:variable>
        <xsl:apply-templates
             select="msxsl:node-set($vRTF-FirstPass)/node()"
             mode="second-pass"/>
    </xsl:template>
    <xsl:template match="node()|@*" mode="second-pass">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" mode="second-pass"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="HL01" mode="second-pass">
        <xsl:copy>
            <xsl:variable name="vPosition">
                <xsl:number level="any"/>
            </xsl:variable>
            <xsl:value-of select="$vPosition + 1"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

С любым входом (не используется), вывод:

<Outer>
    <HL>
        <HL01>1</HL01>
    </HL>
    <Inner>
        <HL01>2</HL01>
    </Inner>
    <HL>
        <HL01>3</HL01>
    </HL>
</Outer>

Примечание : использование функции расширения node-set() (найдите правильный URI пространства имен для вашей реализации процессора XSLT или просто обновите среду до XSLT 2.0 и забудьте node-set()). Режимы на всякий случай. Конечно, вы должны вывести в переменную $vRTF-FirstPass все нужные вам выходные данные: apply-templates, call-template или ... что угодно.

РЕДАКТИРОВАТЬ : Вы можете заменить правило "HL01" на другой аналогичный, но более короткий шаблон содержимого:

<xsl:copy>
    <xsl:value-of select="count(preceding::HL01) + 2"/>
</xsl:copy>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...