Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在xslt中设置标志/变量以再次输入if(与转换为Junit格式相关)_Xslt_Variables_Junit_Params - Fatal编程技术网

如何在xslt中设置标志/变量以再次输入if(与转换为Junit格式相关)

如何在xslt中设置标志/变量以再次输入if(与转换为Junit格式相关),xslt,variables,junit,params,Xslt,Variables,Junit,Params,我正在通过xslt读取一个外部日志文件,我想找到一行。 一旦我找到它,我想打印所有的行,直到我碰到另一行。 对于一个非常大的日志文件,我需要重复这样做。 每个迭代都有一个唯一的id和日志文件,相关信息由 “迭代次数:X”直到“迭代次数X+1”(或EOF) 这是我的xsl:(相关代码在failure标签中) 所需的xml输出如下所示:(详细输出仅在失败时显示) 我尝试使用for each group(甚至是带有键的Muenchian分组)来解决这个问题,但失败了,因为填充不包含节点,因此不允许执

我正在通过xslt读取一个外部日志文件,我想找到一行。 一旦我找到它,我想打印所有的行,直到我碰到另一行。 对于一个非常大的日志文件,我需要重复这样做。 每个迭代都有一个唯一的id和日志文件,相关信息由 “迭代次数:X”直到“迭代次数X+1”(或EOF)

这是我的xsl:(相关代码在failure标签中)

所需的xml输出如下所示:(详细输出仅在失败时显示)



我尝试使用for each group(甚至是带有键的Muenchian分组)来解决这个问题,但失败了,因为填充不包含节点,因此不允许执行许多有用的操作

模拟“正常编码”(即过程)循环的蛮力方法是使用递归。但要做到这一点,您需要能够使用params。然后,您可以通过定义布尔参数“定义布尔标志”,并在需要更改时为其传递不同的值。或者更好的是,当您想停止打印行时,不要重复

以下是样式表:

<?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>
我相信这是理想的输出


这似乎不是一个非常优雅的解决方案,但是当要分组的项不是节点时,我不知道如何进行。还有人有想法吗?

像这样的想法怎么样:

<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>

...
  • 在xsl运行之前,将日志文件拆分为多个日志文件。 每个日志文件将命名为“logfile.txt-X”,其中X是迭代编号。 现在,您只需打印特定的日志文件:


你觉得怎么样

此转换:

<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>
 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 
那么这个呢:

<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>


+回答得好。即使是其他解决方案,我认为在处理文本时也会依赖正则表达式。我会尝试一下。如果xslt支持将逻辑导出到外部脚本(python/bash/perl/js)怎么样?我过去解决过这种问题,将unparsed-text()的每一行包装到一个元素中,这样就可以使用每个组的位置。(XSLT 3.0通过允许模式匹配原子值来解决这一问题)。我想到了一个更好的解决方案,它将更加注重性能。为什么不在运行xsl之前将日志文件拆分为小文件,这些文件的名称与迭代编号相对应,这样您只需在失败时打印正确的日志文件。@Michael:谢谢,好主意。(将每个项包装在一个元素中。)如何使xsl标识f:find?xmlspy对错误大喊大叫。谢谢。。。我试图做类似的事情,但XPath 2.0还不够流利,我的后口袋里还没有像
find
subsequence
这样的函数。问得好,+1。请参阅我的答案,以获得完整且简单的解决方案。:)+一个好问题。请参阅我的XSLT 2.0答案,答案完全基于
tokenize()
。我不清楚日志平面文本与最后显示的XML之间的关系。此外,您是否可以更好地扩展“一旦找到它,我想打印所有行,直到找到另一行。我需要对一个非常大的日志文件重复执行此操作。每个迭代都有一个唯一的id,日志文件通过“迭代编号:X”将相关信息分隔为“迭代编号X+1”(或EOF)。@empo。关系如下。上下文是jenkins的xUnit插件,它需要一个XSL文件,以便将自定义XML转换为junit XML。XSL就是这样做的。附加日志文件是整个测试的日志文件,它打印出XML中没有出现的附加错误消息。这个问题的目的是告诉XSL,一旦某个测试失败,就找到日志文件的正确部分,并将其嵌入XSL将创建的输出XML中(在标记下)。@empo:日志文件的格式化方式是打印原始XML上显示的“迭代号:X”。因此,每个迭代对应于XML中的一个部分(例如,一个节点)。显然,最后一个节点将由EOF终止,而不是另一个“迭代编号:X”行。我希望这能澄清问题。哇,我觉得这对我来说太复杂了。我想如果将来不得不修改的话,我将很难修改它。@Eyal我同意。我认为,如果将$len、$start、$end从for循环中移到普通XSLT变量中,阅读起来会更容易。这绝对是一个很好的例子,说明了如何利用XPath 2.0提供的新迭代功能:)(+1)@Dimitre,我很好奇为什么要使用嵌入式
for
循环来填充$start和$end。。。您是否使用了
find()
?@Eyal:修改并不难——实际上,将函数作为参数(la FXSL)传递到任何找到的行上都很容易。这样做可以实现绝对的灵活性。当然,特别是如果您已经在XSLT之外对日志文件进行了一些处理。我认为这在磁盘/内存上会容易得多,因为原始日志文件非常大,我必须在每次失败的测试中重复它。我知道这不是最好的干净解决方案,但它是迄今为止唯一解决我问题的方法。我希望,一旦我对xsl有了更好的了解,我就可以重新讨论这个问题,并在其他解决方案的基础上实现。+1标记化()的一个有趣用法。请注意,您的代码假定“迭代次数:70”和行尾之间没有任何内容。。。这可能永远是真的。我们不必接受OP将日志文件标记为一系列单独的行的初始步骤,这是一个很好的见解。但是这可以作为一个通用解决方案吗?我的日志文件目前的迭代次数为1…350。这是否只适用于几个连续的迭代?@Eyal:如果您的输入样本足够正确,能够反映您的实际用例,那么您可以将其用作一般解决方案
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
<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>
<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>
<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 
<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