我有xml,essentialy如下所示(我的实际.xml是包含VStudio和DotCover构建输出的联合的构建日志):
<buildlog>
<Projects>
<project name="project1.csproj" />
<project name="project2.csproj" />
<project name="project3.csproj" />
<project name="project4.csproj" />
</Projects>
<Root>
<Assembly Name="project1" />
<Assembly Name="project2" />
</Root>
</buildlog>
我需要一个列表,列出在Root / Assembly节点集中@Name上没有相应@name匹配的所有项目节点。我的目标是生成一个报告,显示所有没有代码覆盖率的项目。
这是我的xsl样式表的开头:
<xsl:template match="/">
<xsl:apply-templates select="buildlog/Projects" />
</xsl:template>
<xsl:template match="Projects">
<table>
<tr>
<td>Assemblies Not Covered:</td>
<td><xsl:value-of select="count(./project)"/></td>
</tr>
</table>
<xsl:apply-templates select="project" />
</xsl:template>
<xsl:template match="project">
<table>
<tr>
<td style="padding-left:30px">
<xsl:value-of select="substring-before(./@name,'.csproj')"/>
</td>
</tr>
</table>
</xsl:template>
提前致谢。
临时解决方案
目前我使用ms:脚本扩展解决了我的问题。下面是代码。 不是最优雅的,它只是一个Windows解决方案,但它解决了这个问题。生病 其他人推荐的内容,并在评论部分回答。
Here's my solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:dsi="urn:dsi-scripts">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:apply-templates select="buildlog/Projects" />
</xsl:template>
<xsl:template match="Projects">
<table>
<tr>
<td>Assemblies Not Covered:</td>
</tr>
</table>
<xsl:apply-templates select="project" />
</xsl:template>
<xsl:template match="project">
<xsl:variable name="assemblies" select="//Assembly" />
<xsl:if test="not(dsi:HasCoverage($assemblies/@Name, ./@name))">
<table>
<tr>
<td style="padding-left:30px">
<xsl:value-of select="substring-before(./@name,'.csproj')"/>
</td>
</tr>
</table>
</xsl:if>
</xsl:template>
<xsl:template match="Assembly">
<table>
<tr>
<td style="padding-left:30px">
<xsl:value-of select="@Name"/>
</td>
</tr>
</table>
</xsl:template>
<ms:script language="C#" implements-prefix="dsi">
<![CDATA[
public bool HasCoverage(XPathNodeIterator assemblies, string project)
{
bool result = false;
while(assemblies.MoveNext())
{
if(assemblies.Current.Value == project.Replace(".csproj",string.Empty))
{
result = true;
break;
}
}
return result;
}
]]>
</ms:script>
</xsl:stylesheet>
答案 0 :(得分:3)
我需要一个包含所有项目节点的列表 没有相应的@name 匹配@中的@Name 根/程序集节点
使用强>:
/*/Projects/project
[not(substring-before(@name, '.csproj') = /*/Root/Assembly/@Name)]
此XPath表达式精确选择所需的project
元素。
完整解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match=
"Projects/project
[not(substring-before(@name, '.csproj')
=
/*/Root/Assembly/@Name)] ">
<xsl:value-of select="concat(@name,'
')"/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<buildlog>
<Projects>
<project name="project1.csproj" />
<project name="project2.csproj" />
<project name="project3.csproj" />
<project name="project4.csproj" />
</Projects>
<Root>
<Assembly Name="project1" />
<Assembly Name="project2" />
</Root>
</buildlog>
生成了想要的结果:
project3.csproj
project4.csproj
如果确实需要更高的效率,则应使用密钥。