【发布时间】:2011-05-07 08:41:42
【问题描述】:
我运行 CruiseControl.NET 并尝试构建一个 XSL 样式表,该样式表从 XML 构建日志中提取有关损坏的单元测试的某些信息。对于每个损坏的单元测试,我想在 XSL 中获取单元测试的名称、单元测试所在的类名以及失败消息。目前,我可以获取单元测试名称和失败消息,但是我无法获取类名。我认为这是因为单元测试的类名仅包含在 XML 构建日志的不同区域中,而且我是 XSL 的菜鸟。这是我的 XSL 样式表的精简示例:
<!-- Unit tests -->
<xsl:template match="/">
<table border="1" width="100%">
<tr>
<th align="left">Class</th>
<th align="left">Method</th>
<th align="left">Message</th>
</tr>
<xsl:apply-templates select="/cruisecontrol/build/*[local-name()='TestRun']/*[local-name()='Results']/*[local-name()='UnitTestResult']"/>
</table>
</xsl:template>
<!-- Failed uint test -->
<xsl:template match="*[local-name()='UnitTestResult'][@outcome='Failed']">
<tr>
<td>
<xsl:apply-templates select="/cruisecontrol/build/*[local-name()='TestRun']/*[local-name()='TestDefinitions']/*[local-name()='UnitTest'][@id=@testId]"/>
</td>
<td>
<xsl:value-of select="@testName"/>
</td>
<td>
<xsl:value-of select="*[local-name()='Output']/*[local-name()='ErrorInfo']/*[local-name()='Message']"/>
</td>
</tr>
</xsl:template>
<!-- Failed unit test class name -->
<xsl:template match="/cruisecontrol/build/*[local-name()='TestRun']/*[local-name()='TestDefinitions']/*[local-name()='UnitTest']">
<xsl:value-of select="@className"/>
</xsl:template>
这是一个精简的 XML 构建日志示例:
<cruisecontrol>
<build>
<TestRun>
<TestDefinitions>
<UnitTest name="MyUnitTest" storage="Test.dll" id="b17e5b2a-47d0-5f78-1750-07c8ac14518c">
<TestMethod className="UnitTests.cs" name="MyUnitTest" />
</UnitTest>
...
</TestDefinitions>
<Results>
<UnitTestResult testId="b17e5b2a-47d0-5f78-1750-07c8ac14518c" testName="MyUnitTest" outcome="Failed">
<Output>
<ErrorInfo>
<Message>Assert.AreEqual failed</Message>
</ErrorInfo>
</Output>
</UnitTestResult>
...
</Results>
</TestRun>
</build>
</cruisecontrol>
这是当前的输出:
单元测试类名:
单元测试方法名称:MyUnitTest
失败消息:Assert.AreEqual 失败
这是所需的输出:
单元测试类名:UnitTests.cs
单元测试方法名称:MyUnitTest
失败消息:Assert.AreEqual 失败
我的问题是类名总是空的。我正在尝试使用 UnitTestResult 节点的 testId 属性来引用文档中其他地方的正确 UnitTest 节点。我需要什么 XSL 或 Xpath 魔法才能实现我的目标?
【问题讨论】:
-
你为什么使用那些
local-name()而不是直接的节点名称?假设没有 XML 命名空间(至少在您发布的 XML 中没有),/cruisecontrol/build/TestRun/Results/UnitTestResult将等同于/cruisecontrol/build/*[local-name()='TestRun']/*[local-name()='Results']/*[local-name()='UnitTestResult']。 -
我不太确定;我在这方面是一个相当大的菜鸟,并且正在接受别人以前的工作。感谢您的帮助和评论;将看看改变它。我绝对愿意接受有关清理和采用更好做法的进一步建议。
标签: xslt xpath cruisecontrol.net stylesheet