Reputation: 4170
I am trying to convert Apples plist file into a JUnit XML format so Hudson/Jenkins can read the results.
I have a plist file output similar to this:
<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>
which I need to convert to JUnit XML. Here is the output iI expect for the plist fiel above:
<?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>
Currently I have this 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>
How can I edit the XSL above to find any error messages in between the two dict/string[2] = 'Test A' and insert the message into the value of <failure>
? I am not sure how to do this because the Error message is contained in another <dict>
node.
EDIT:
Ok I have broken this down into pseudo ish code:
Count all the nodes with integer = 4.
Find out the position of each of the nodes with integer = 4 and store in a variable
Go through each node with integer = 4 and find any string[1] = 'Fail' before next node with integer = 4.
If any string[1] = 'Fail' then find and string[1] = 'Error' before next node with integer = 4 and after previous node with integer = 4.
failure
with string[2] from current node and string[2] from previous node with integer = 4.failure
with string[2] from previous node with integer = 4.node referring to plist/dict/array/dict
Is this possible with XSL?
Upvotes: 0
Views: 1176
Reputation: 3738
Your rules are slightly confusing, but I believe I have a solution for you.
When this 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>
..is applied to the provided 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>
...the expected result is produced:
<?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>
Explanation:
<testsuites>
and <testsuite>
elements. The XSLT processor is then instructed to process all <dict>
descendants whose <integer>
child has a value of 4.<dict>
elements whose first <string>
child has a value of "Fail". In this case, a new <testcase>
and <failure>
element pair is created and given a value that conforms to the rules you have provided.<dict>
elements whose first <string>
child has a value of anything other than "Fail". In this case, a new <testcase>
element is created and given values per your rules.Upvotes: 1