通过XSL Plist到JUnit XML

时间:2012-10-26 17:29:47

标签: xml xslt plist

我正在尝试将Apples plist文件转换为JUnit XML格式,因此Hudson / Jenkins可以读取结果。

我有一个与此类似的plist文件输出:

<plist><dict><array>
        <dict>
            <key>LogType</key>
            <string>Pass</string>
            <key>Message</key>
            <string>Test 1</string>
            <key>Timestamp</key>
            <date>2012-10-26T09:42:41Z</date>
            <key>Type</key>
            <integer>4</integer>
         </dict>
         <dict>.....</dict>
         .
         .
         .
         <dict>
            <key>LogType</key>
            <string>Pass</string>
            <key>Message</key>
            <string>Test 1</string>
            <key>Timestamp</key>
            <date>2012-10-26T09:43:27Z</date>
            <key>Type</key>
            <integer>5</integer>
         </dict>
         <dict>
            <key>LogType</key>
            <string>Fail</string>
            <key>Message</key>
            <string>Inserting content to a group</string>
            <key>Timestamp</key>
            <date>2012-10-26T09:49:13Z</date>
            <key>Type</key>
            <integer>4</integer>
        </dict>
        <dict>.....</dict>
        .
        .
        .
        <dict>
            <key>LogType</key>
            <string>Error</string>
            <key>Message</key>
            <string>VerboseError: target.frontMostApp().mainWindow().buttons()[3] could not be tapped</string>
            <key>Screenshot</key>
            <string></string>
            <key>Timestamp</key>
            <date>2012-10-26T09:50:12Z</date>
            <key>Type</key>
            <integer>3</integer>
        </dict>
        <dict>
            <key>LogType</key>
            <string>Fail</string>
            <key>Message</key>
            <string>Inserting content to a group</string>
            <key>Screenshot</key>
            <string></string>
            <key>Timestamp</key>
            <date>2012-10-26T09:50:13Z</date>
            <key>Type</key>
            <integer>7</integer>
        </dict>
</array></dict>
</plist>

我需要转换为JUnit XML。以下是上述plist场所预期的输出:

<?xml version="1.0"?>
<testsuites>
    <testsuite>
        <testcase classname="Test 1" name="Test 1"/>
        <testcase classname="Inserting content to a group" name="Inserting content to a group">
            <failure>Inserting content to a group - VerboseError: target.frontMostApp().mainWindow().buttons()[3] could not be tapped< </failure>
        </testcase>
    </testsuite>
</testsuites>

目前我有这个XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <testsuites>
            <testsuite>
                <xsl:for-each select="plist/dict/array/dict">
                    <xsl:if test="integer = 4">
                        <testcase>
                            <xsl:attribute name="classname"><xsl:value-of select="string[2]" /></xsl:attribute>
                            <xsl:attribute name="name"><xsl:value-of select="string[2]"/></xsl:attribute>
                            <xsl:if test="string[1] = 'Fail'">
                                <failure>
                                    <xsl:attribute name="type"><xsl:value-of select="integer" /></xsl:attribute><xsl:value-of select="string[2]" />                                           
                                </failure>
                            </xsl:if>
                        </testcase>
                    </xsl:if>
                </xsl:for-each>
            </testsuite>
        </testsuites>
    </xsl:template>
</xsl:stylesheet>

如何编辑上面的XSL以查找两个dict / string [2] ='Test A'之间的任何错误消息,并将消息插入<failure>的值?我不知道如何执行此操作,因为错误消息包含在另一个<dict>节点中。

修改

好的我已将其分解为伪ish代码:

  1. 使用integer = 4计算所有节点。

  2. 找出每个具有整数= 4的节点的位置并存储在变量中

  3. 使用integer = 4遍历每个节点,并在整数= 4的下一个节点之前找到任何字符串[1] ='Fail'。

    1. 如果任何字符串[1] ='失败',则在具有整数= 4的下一个节点之前以及在整数= 4之前的节点之后找到并且字符串[1] ='错误'。

      1. 如果有任何字符串[1] ='错误',则从当前节点输出带有字符串[2]的failure,并使用整数= 4从前一节点输出字符串[2]。
    2. 另外输出failure,其字符串[2]来自上一节点,整数= 4。
  4. 节点引用plist / dict / array / dict

    这可以用XSL吗?

1 个答案:

答案 0 :(得分:1)

你的规则有点令人困惑,但我相信我有一个解决方案。

当这个XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/*">
    <testsuites>
      <testsuite>
        <xsl:apply-templates select="/*/*/*/dict[integer = '4']" />
      </testsuite>
    </testsuites>
  </xsl:template>

  <xsl:template match="dict[string[1] = 'Fail']">
    <testcase classname="{string[2]}" name="{string[2]}">
      <failure>
        <xsl:value-of select="string[2]" />
        <xsl:if test="following-sibling::dict[1]/string[1] = 'Error'">    
          <xsl:value-of select="concat( ' - ', following-sibling::dict[string[1] = 'Error'][1]/string[2])" />
        </xsl:if>
      </failure>
    </testcase>
  </xsl:template>

  <xsl:template match="dict[not(string[1] = 'Fail')]">
    <testcase classname="{string[2]}" name="{string[2]}" />
  </xsl:template>
</xsl:stylesheet>

..适用于提供的XML:

<?xml version="1.0" encoding="utf-8"?>
<plist>
  <dict>
    <array>
      <dict>
        <key>LogType</key>
        <string>Pass</string>
        <key>Message</key>
        <string>Test 1</string>
        <key>Timestamp</key>
        <date>2012-10-26T09:42:41Z</date>
        <key>Type</key>
        <integer>4</integer>
      </dict>
      <dict>
        <key>LogType</key>
        <string>Pass</string>
        <key>Message</key>
        <string>Test 1</string>
        <key>Timestamp</key>
        <date>2012-10-26T09:43:27Z</date>
        <key>Type</key>
        <integer>5</integer>
      </dict>
      <dict>
        <key>LogType</key>
        <string>Fail</string>
        <key>Message</key>
        <string>Inserting content to a group</string>
        <key>Timestamp</key>
        <date>2012-10-26T09:49:13Z</date>
        <key>Type</key>
        <integer>4</integer>
      </dict>
      <dict>
        <key>LogType</key>
        <string>Error</string>
        <key>Message</key>
        <string>VerboseError:
        target.frontMostApp().mainWindow().buttons()[3] could not
        be tapped</string>
        <key>Screenshot</key>
        <string />
        <key>Timestamp</key>
        <date>2012-10-26T09:50:12Z</date>
        <key>Type</key>
        <integer>3</integer>
      </dict>
      <dict>
        <key>LogType</key>
        <string>Fail</string>
        <key>Message</key>
        <string>Inserting content to a group</string>
        <key>Screenshot</key>
        <string />
        <key>Timestamp</key>
        <date>2012-10-26T09:50:13Z</date>
        <key>Type</key>
        <integer>7</integer>
      </dict>
    </array>
  </dict>
</plist>

...产生预期结果:

<?xml version="1.0"?>
<testsuites>
  <testsuite>
    <testcase classname="Test 1" name="Test 1" />
    <testcase classname="Inserting content to a group"
    name="Inserting content to a group">
      <failure>Inserting content to a group - VerboseError:
      target.frontMostApp().mainWindow().buttons()[3] could not be
      tapped</failure>
    </testcase>
  </testsuite>
</testsuites>

<强>解释

  • 第一个模板会创建新的<testsuites><testsuite>元素。然后指示XSLT处理器处理<dict>子项值为4的所有<integer>个后代。
  • 第二个模板匹配其第一个<dict>子元素值为“Fail”的所有<string>个元素。在这种情况下,会创建一个新的<testcase><failure>元素对,并为其提供符合您提供的规则的值。
  • 最终模板匹配所有<dict>个元素,其第一个<string>子元素的值除“失败”以外的任何值。在这种情况下,会创建一个新的<testcase>元素,并根据您的规则给出值。