XSLT to find all nodes in one list that are not in another

I have xml, which essentially looks like this (my actual .xml is the assembly log containing the union of VStudio and the output of the DotCover assembly):

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

I need a list of all project nodes that do not have a corresponding @name to @Name match in the Root / Assembly node set. My goal here is to create a report showing all projects that do not have code coverage.

Here is the beginning of my xsl stylesheet:

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

Thanks in advance.

INTERIM DECISION

Currently, I have solved my problem using ms: script extensions. Below is the code. Not the most elegant option - this solution is only for Windows, but it solved the problem. Sick things that other people recommend and respond in the comments section.

Here 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>
+3
1

@name @Name Root/Assembly

/*/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,'&#xA;')"/>
 </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

, .

+3

Source: https://habr.com/ru/post/1785282/


All Articles