RE: [xsl] Testing if something is not there

Subject: RE: [xsl] Testing if something is not there
From: "Miller, James V (CRD)" <millerjv@xxxxxxxxxx>
Date: Tue, 6 Nov 2001 08:33:48 -0500
Thanks for tips!  I was about half-way there.  You use a few more variables than I was using. Are
there speed advantages to using variables like $Test rather than using XPaths in template match or
for-each constructs?

I do have a lot of Tests under each Site.  Usually there are about 500. So the tip to use

<xsl:key name="TestSites" match="Test"
         use="concat(../../SiteName, '::', FullName)" />

was VERY helpful.  Without the above key, it was taking about 30 seconds to process my XML file.
With the above key, the processing time was cut to 4 seconds!

This is great!



-----Original Message-----
From: Jeni Tennison [mailto:jeni@xxxxxxxxxxxxxxxx]
Sent: Tuesday, November 06, 2001 6:27 AM
To: Miller, James V (CRD)
Cc: 'Xsl-List (E-mail)
Subject: Re: [xsl] Testing if something is not there


Hi Jim,

> I can achieve this result using xsl:key and the key() function.
> While difficult to grok, it is VERY FAST. Now the kicker. Not every
> "Test" is run on every "Site" (not every "Test/FullName" needs to
> appear under every "BuildStamp"). What I really want to do is "fill
> out" the Test elements, so that every BuildName/Site appears inside
> of every Test element. If the Site did not run the Test, then the
> "Status" will be set to "NA".

If you want to make every BuildName/Site appear, then you need to
iterate over every BuildName/Site. You should still use the key to get
hold of the names of the tests (unless you have them listed
elsewhere):

  <xsl:variable name="BuildStamps" select="BuildStamp" />
  <xsl:for-each select="$BuildStamps/Testing/Tests/Test
                          [count(.|key('TestNames', FullName)[1]) = 1]">
    <xsl:variable name="TestName" select="FullName" />
    <Test>
      <Name><xsl:value-of select="$TestName" /></Name>
      ...
    </Test>
  </xsl:for-each>

Then you can iterate over each of the BuildStamp elements to work out
whether the site carries out the test or not. If it does, then you add
the Result with a Status from the relevant Test/Result. If it doesn't,
then the Status takes the value NA:

  <xsl:variable name="BuildStamps" select="BuildStamp" />
  <xsl:for-each select="$BuildStamps/Testing/Tests/Test
                          [count(.|key('TestNames', FullName)[1]) = 1]">
    <xsl:variable name="TestName" select="FullName" />
    <Test>
      <Name><xsl:value-of select="$TestName" /></Name>
      <xsl:for-each select="$BuildStamps/Testing">
        <xsl:variable name="Test"
                      select="Tests/Test[FullName = $TestName]" />
        <Result>
          <xsl:copy-of select="SiteName" />
          <Status>
            <xsl:choose>
              <xsl:when test="$Test">
                <xsl:value-of select="$Test" />
              </xsl:when>
              <xsl:otherwise>NA</xsl:otherwise>
            </xsl:choose>
          </Status>
        </Result>
      </xsl:for-each>
    </Test>
  </xsl:for-each>

If you have *lots* of tests within each site, then you could consider
having a key to enable you to retrieve the Test element with a
particular name for a particular site. The key would look like:

<xsl:key name="TestSites" match="Test"
         use="concat(../../SiteName, '::', FullName)" />

and in the xsl:for-each from above, you would set the $Test variable
with the following path instead:

  key('TestSites', concat(SiteName, '::', $TestName))

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread