как установить флаг / переменную в xslt для ввода, если снова (связано с преобразованием в формат Junit) - PullRequest
4 голосов
/ 16 июня 2011

Я читаю внешний файл журнала через xslt и хочу найти определенную строку.Как только я нахожу это, я хочу напечатать все строки, пока я не достигну другой строки.Мне нужно сделать это несколько раз для очень большого файла журнала.каждая итерация имеет уникальный идентификатор и файл журнала отделял релевантную информацию от «номера итерации: X» до «номера итерации X + 1» (или EOF).

Вот мой xsl: (соответствующий код находится в теге сбоя)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" indent="yes" />    
    <xsl:template match="/">
        <testsuites>        
            <xsl:variable name="buildName" select="//rest/*/test_name"/>    
            <xsl:variable name="numberOfTests" select="count(//rest/*/iter_num)"/>
            <xsl:variable name="numberOfFailures" select="count(//rest/*/status [.= 'Fail'])" />    
            <xsl:variable name="numberSkipped" select="count(//rest/*/status [.!='Pass' and .!='Fail'])" /> 
            <xsl:variable name="logfile" select="//rest/@logfile" />    
            <xsl:variable name="testfile" select="//rest/@testFile" />

            <testsuite name="QE AUTOMATION TESTS"
                tests="{$numberOfTests}" time="0"
                failures="{$numberOfFailures}"  errors="0"
                skipped="{$numberSkipped}">

                <xsl:for-each select="//rest/*">
                    <xsl:variable name="testName" select="test_name"/>
                    <xsl:variable name="executionId" select="iter_num"/>
                    <xsl:variable name="start_time" select="fn:replace(start_time,' ','T')" />
                    <xsl:variable name="end_time" select="fn:replace(end_time,' ','T')"/>
                    <xsl:variable name="test_parameters" select="test_parameters"/>
                    <xsl:variable name="test_positive" select="test_positive"/>
                    <xsl:variable name="time_diff" select="xs:dateTime($end_time)-xs:dateTime($start_time)"/>
                    <xsl:variable name="duration_seconds" select="seconds-from-duration($time_diff)"/>
                    <xsl:variable name="duration_minutes" select="minutes-from-duration($time_diff)"/>  
                    <xsl:variable name="duration_hours" select="hours-from-duration($time_diff)"/>      
                    <xsl:variable name="outcome" select="status"/>  
                    <xsl:variable name="message" select="$buildName"/>  
                                <testcase classname="qe-tests.{local-name(.)}"
                                    name="{$testName}"
                                    time="{$duration_hours*3600 + $duration_minutes*60 + $duration_seconds }">
<xsl:if test="contains($outcome, 'Fail')"> 
    <failure>
        <xsl:param name="executionEnd" select="$executionId +1"/>
        <xsl:variable name="postIterX" select="tokenize(.,concat('Iteration number: ',$executionId,'\r?\n'),'m')[2]"/>
        <xsl:variable name="inIterX" select="tokenize($postIterX, concat('\r?\n.*Iteration number: ',$executionEnd,'\r?\n?'),'m')[1]"/>
        <xsl:value-of select="$inIterX"/>  
    </failure>
</xsl:if>
                            </testcase>
                </xsl:for-each>
            </testsuite>
        </testsuites>
    </xsl:template>
</xsl:stylesheet>

я обновлен до кода для использования решения @empo, но в этом случае при использовании xsl: param произошла ошибкаway.

файл журнала, который у меня есть, похож на этот (это упрощенный фрагмент) (начните со строки «Итерация 70» и в этом примере остановитесь на Итерации 71)

2011-06-15 15:38:07,126 - networks - INFO - Compared entities are equal
2011-06-15 15:38:07,152 - rest-Main - INFO - Test status for iteration 60 Pass
2011-06-15 15:38:07,187 - rest-Main - INFO - Test name: add Network To Cluster
2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 70
2011-06-15 15:38:07,187 - rest-Main - INFO - Test action: addNetworkToCluster
2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE
2011-06-15 15:38:07,152 - rest-Main - INFO - Test status for iteration 70 Fail
2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 71
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: DDDDD
 2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE

* EOF

желаемый вывод XML выглядит следующим образом: (подробный вывод будет показан только при ошибке)

<?xml version="1.0" encoding="UTF-8"?>
<testsuites xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <testsuite name="QE AUTOMATION TESTS" tests="2" time="0" failures="1" errors="0" skipped="0">
        <testcase classname="qe-tests.Network" name="Add Network to Cluster="3">
            <failure>
2011-06-15 15:38:05,674 - rest-Main - INFO - Iteration number: 70
2011-06-15 15:38:05,674 - rest-Main - INFO - Running function: networks.addNetworkToCluster
2011-06-15 15:38:05,675 - rest-Main - INFO - Running command: testStatus=addNetworkToCluster('TRUE',network='testrest1',cluster='RestCluster1')
2011-06-15 15:38:05,675 - networks - DEBUG - GET request content is --  url:http://localhost:8080/rhevm-api/networks 
2011-06-15 15:38:05,887 - networks - DEBUG - Response body for GET request is: &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE
</failure>
        </testcase>
        <testcase classname="qe-tests.network" name="Add network to iscsi" time="1"/>
    </testsuite>
</testsuites>

исходный XML выглядит так: (фрагмент) «Сеть» - это только один из возможных дочерних элементов (естьбольше похоже на 'Центры обработки данных' например)

<?xml version="1.0" encoding="UTF-8"?>
<rest logfile="log.txt" testFile="REST_API.ods">
    <Network>
        <test_parameters>name='RestDataCenter2',storage_type='iscsi',version='3.0'</test_parameters>
        <test_name>Add Network to cluster</test_name>
        <end_time>2011-06-13 01:22:56</end_time>
        <iter_num>70</iter_num>
        <test_positive>TRUE</test_positive>
        <tcms_test_case/>
        <start_time>2011-06-13 01:22:55</start_time>
        <status>Fail</status>
    </Network>
    <Network>
        <test_parameters>name='RestDataCenter2',storage_type='iscsi',version='3.0'</test_parameters>
        <test_name>Add network to iscsi</test_name>
        <end_time>2011-06-13 01:22:56</end_time>
        <iter_num>71</iter_num>
        <test_positive>TRUE</test_positive>
        <tcms_test_case/>
        <start_time>2011-06-13 01:22:55</start_time>
        <status>Pass</status>
    </Network>
</rest>

Ответы [ 5 ]

1 голос
/ 16 июня 2011

Что по этому поводу:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="executionId" select="70"/>
    <xsl:param name="executionEnd" select="71"/>

    <xsl:template match="/">

        <xsl:variable name="post70" select="tokenize(
            .,
            concat('Iteration number: ',$executionId,'\r?\n'),'m')[2]"/>

        <xsl:variable name="in7071" select="tokenize(
            $post70,
            concat('\r?\n.*Iteration number: ',$executionEnd,'\r?\n?'),'m')[1]"/>

        <xsl:value-of select="$in7071"/>

    </xsl:template>

</xsl:stylesheet>

Производит:

2011-06-15 15:38:07,187 - rest-Main - INFO - Test action: attachHostNic
2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE
1 голос
/ 16 июня 2011

Это преобразование :

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="my:my">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vLines" as="xs:string*" select=
  "tokenize(/, '\r?\n')"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "for $x in my:procesStartStop($vLines,
                                 'Iteration number: 70',
                                 'Iteration number: 71')
     return ($x, '&#xA;')
   "
   />
 </xsl:template>

 <xsl:function name="my:procesStartStop" as="xs:string*">
  <xsl:param name="pLines" as="xs:string*"/>
  <xsl:param name="pStart" as="xs:string"/>
  <xsl:param name="pStop" as="xs:string"/>

  <xsl:sequence select=
   "for $len in count(($pLines, $pStop)),
        $start in
           (for $i in 1 to $len
             return
                if(contains($pLines[$i], $pStart))
                  then $i
                  else()
            )
             [1],

        $end in
           (for $j in 1 to $len
             return
                if(contains($pLines[$j], $pStop))
                  then $j
                  else()
            )
             [1]

      return
        subsequence($pLines, $start, $end -$start +1)

   "/>
 </xsl:function>

</xsl:stylesheet>

при применении к этому документу XML (содержащему предоставленный текст):

<t>
    2011-06-15 15:38:07,126 - networks - INFO - Compared entities are equal
    2011-06-15 15:38:07,152 - rest-Main - INFO - Test status for Pass
    2011-06-15 15:38:07,187 - rest-Main - INFO - Test name: Attach Host NIC To Network
    2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 70
    2011-06-15 15:38:07,187 - rest-Main - INFO - Test action: attachHostNic
    2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
    2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE
    2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 71
    2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: DDDDD
</t>

выдает нужный, правильный ответ :

 2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 70
 2011-06-15 15:38:07,187 - rest-Main - INFO - Test action: attachHostNic 
 2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes 
 2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE 
 2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 71 
1 голос
/ 16 июня 2011

Как насчет этого:

<xsl:variable name="lines" select="tokenize(unparsed-text($logfile), '\r?\n')"/>
<xsl:variable name="start" select="f:find($lines 'Iteration 70')[1]"/>
<xsl:variable name="end" select="f:find($lines, 'Iteration 71')[1]"/>
<xsl:for-each select="subsequence($lines, $start, $end - $start + 1)">
   ...
</xsl:for-each>

<xsl:function name="f:find" as="xs:integer*">
  <xsl:param name="lines" as="xs:string*"/>
  <xsl:param name="content" as="xs:string"/>
  <xsl:for-each select="$lines">
     <xsl:if test="contains(., content)">
       <xsl:sequence select="position()"/>
     </xsl:if>
  </xsl:for-each>
</xsl:function>
1 голос
/ 16 июня 2011
  • Разделите файл журнала на несколько файлов журнала перед запуском xsl. каждый файл журнала будет называться «logfile.txt-X», где X - номер итерации. теперь все, что вам нужно сделать, это распечатать конкретный файл журнала:

<xsl:variable name="executionId" select="'70'"/>

<xsl:variable name="logfile" select="'logfile.txt'" />

<xsl:variable name="iter_log" select="concat($logfile,'-',$executionId)"/>

<xsl:variable name="output" select="unparsed-text($iter_log)">

<xsl:value-of select="$output" />

что вы думаете?

1 голос
/ 16 июня 2011

Я попытался решить эту проблему, используя for-each-group (или даже мюнхенскую группировку с ключами), и потерпел неудачу, так как совокупность не состоит из узлов, и поэтому многие из полезных операций запрещены.

Грубый способ эмулировать цикл "нормального кодирования" (т. Е. Процедурный) заключается в использовании рекурсии.Но для этого нужно уметь использовать params.Затем вы должны «определить флаг bool», определив логический параметр и передав ему другое значение, когда вы захотите изменить его.Или еще лучше, когда вы хотите прекратить печатать строки, просто не повторяйте.

Вот таблица стилей:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="2.0">
   <!-- $executionId is defined before and read from the xml, but for convenience: -->
   <xsl:variable name="executionId" select="'70'"/>
   <xsl:variable name="iter_line" select="concat('Iteration number: ',$executionId)"/>
   <xsl:variable name="logfile" select="'logfile.txt'" />
   <xsl:template match="/">
      <xsl:variable name="lines" select="tokenize(unparsed-text($logfile), '\r?\n')" />
      <xsl:call-template name="search-for-start">
         <xsl:with-param name="remaining-lines" select="$lines"/>
      </xsl:call-template>
   </xsl:template>

   <!-- skip lines until we find one that matches the start pattern -->
   <xsl:template name="search-for-start">
      <xsl:param name="remaining-lines" select="()"/>
      <xsl:choose>
         <xsl:when test="contains($remaining-lines[1], $iter_line)">
            <xsl:value-of select="$remaining-lines[1]"/>
            <xsl:text>&#x0a;</xsl:text>
            <xsl:call-template name="output-lines">
               <xsl:with-param name="remaining-lines" select="$remaining-lines[position() > 1]"/>
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <xsl:call-template name="search-for-start">
               <xsl:with-param name="remaining-lines" select="$remaining-lines[position() > 1]"/>
            </xsl:call-template>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <!-- output the given lines, up to the next 'Iteration number: ' -->
   <xsl:template name="output-lines">
      <xsl:param name="remaining-lines"/>
      <xsl:choose>
         <!-- If so, we're done. -->
         <xsl:when test="contains($remaining-lines[1], 'Iteration number: ')" />
         <xsl:otherwise>
            <xsl:value-of select="$remaining-lines[1]"/>
            <xsl:text>&#x0a;</xsl:text>
            <xsl:call-template name="output-lines">
               <xsl:with-param name="remaining-lines" select="$remaining-lines[position() > 1]"/>
            </xsl:call-template>            
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

, которая, протестированная на вашем примере вывода, дает: (после пролога)

2011-06-15 15:38:07,192 - rest-Main - INFO - Iteration number: 70
2011-06-15 15:38:07,187 - rest-Main - INFO - Test action: attachHostNic
2011-06-15 15:38:07,188 - rest-Main - INFO - Run test: yes
2011-06-15 15:38:07,188 - rest-Main - INFO - Test positive: TRUE

, который я считаю желаемым результатом.

Это не кажется очень элегантным решением, но я не знаю, как еще это сделать, когдаэлементы для группировки не являются узлами.У кого-нибудь еще есть идеи?

...