XSLT, чтобы найти все узлы в одном списке, которых нет в другом - PullRequest
3 голосов
/ 13 января 2011

У меня есть xml, который по сути выглядит следующим образом (мой фактический .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>

Мне нужен список всех узлов проекта, которыене соответствует @name имени @Name в наборе узлов Root / Assembly.Моя цель здесь - создать отчет, показывающий все проекты, которые не имеют покрытия кода.

Вот начало моей таблицы стилей 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>

1 Ответ

3 голосов
/ 14 января 2011

Мне нужен список всех узлов проекта, которые не имеют соответствующего совпадения @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

В случае болееэффективность становится действительно необходимой, нужно использовать ключи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...