This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: How to remove double elements?????


Hi Stephan,

> 1.)
> Is there an elegant possibility to remove double elements??? By
> using my version the first element gets lost!!

The reason that your first element gets lost is that you're testing:

  preceding-sibling::computer[1]/@name != @name

which asks whether there's an immediately preceding computer element
whose name attribute isn't the same as the name attribute on this
computer element. This isn't true for the first computer, because it
doesn't have a preceding sibling.

Use:

  not(preceding-sibling::computer[1]/@name = @name)

instead; this asks whether there isn't a preceding sibling computer
element with the same name as this one.

> 2.) 
> Is it possible to get these functionaltities with LESS code
> (especially with LESS variables)??????

Yes, I think so. Let me make sure I understand what you're doing
first, though. Each tool has a name and version, matching a release in
$sw-file. Each release has several computers, each of which has a name
matching a computer in $hw-file.

You want to get a copy of the computers from the $hw-file that are
named by any of the computers under the releases in the $sw-file that
are identified by the set of tools you're looking at.

Can I assume that in the $hw-file, there's only one computer element
with a particular version and name?

If so, I think it would be simpler if you turned it around, so that
you actually went through the computers within the $hw-file, sorted by
their function and name:

  <xsl:for-each select="computer">
    <xsl:sort select="@version" />
    <xsl:sort select="@number" />
    <xsl:variable name="computer" select="." />
    ...
  </xsl:for-each>

For each of them, look in the $sw-file to find out if there are any
releases that contain computers with that name. Set up a key like:

<xsl:key name="releases" match="release" use="computer/@name" />

and then do:

  <xsl:for-each select="computer">
    <xsl:sort select="@version" />
    <xsl:sort select="@number" />
    <xsl:variable name="computer" select="." />
    <xsl:for-each select="$sw-file">
      <xsl:variable name="releases"
                    select="key('releases', $computer/@name)" />
      ...
    </xsl:for-each>
  </xsl:for-each>

Then you need to find out whether there are any tools that share (I
guess) the same name and version as the release. So have a key like:

<xsl:key name="tools" match="tool"
         use="concat(@name, '#', @version)" />

I'll assume that the tools are listed in the $hw-file.
         
Create a variable by going through each of the releases in turn and
try to find a tool with the same name and version. If you find one,
add some text to the variable (it doesn't matter what the text is --
it just acts as a flag so that we can tell that a release has been
identified):

  <xsl:for-each select="computer">
    <xsl:sort select="@version" />
    <xsl:sort select="@number" />
    <xsl:variable name="computer" select="." />
    <xsl:for-each select="$sw-file">
      <xsl:variable name="releases"
                    select="key('releases', $computer/@name)" />
      <xsl:variable name="createCopy">
        <xsl:for-each select="$releases">
          <xsl:variable name="releaseKey"
                        select="concat(@name, '#', @version)" />
          <xsl:for-each select="$hw-file">
            <xsl:if test="key('tools', $releaseKey)">
              Yes, there's a release for this computer
            </xsl:if>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:variable>
      ...
    </xsl:for-each>
  </xsl:for-each>

Then if the $createCopy variable has a string value, you know that you
should create a copy of the particular computer. Just do:

  <xsl:for-each select="computer">
    <xsl:sort select="@version" />
    <xsl:sort select="@number" />
    <xsl:variable name="computer" select="." />
    <xsl:for-each select="$sw-file">
      <xsl:variable name="releases"
                    select="key('releases', $computer/@name)" />
      <xsl:variable name="createCopy">
        <xsl:for-each select="$releases">
          <xsl:variable name="releaseKey"
                        select="concat(@name, '#', @version)" />
          <xsl:for-each select="$hw-file">
            <xsl:if test="key('tools', $releaseKey)">
              Yes, there's a release for this computer
            </xsl:if>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:variable>
      <xsl:if test="string($createCopy)">
        <xsl:copy-of select="$computer" />
      </xsl:if>
    </xsl:for-each>
  </xsl:for-each>

No result tree fragment variables at all.

---

In XSLT 2.0, thanks primarily to general steps and the ability to
construct sequences of values, we'll be able to do this really easily:

  <xsl:variable name="toolkeys"
    select="for $tool in tool return concat(@name, '#', @version)" />
  <xsl:variable name="computerNames"
     select="$sw-file/key('releasekey', $toolkeys)/computer/@name" />
  <xsl:for-each select="$hw-file/key('hw_key', $computerNames)">
    <xsl:sort select="@version" />
    <xsl:sort select="@name" />
    <xsl:copy-of select="." />
  </xsl:for-each>

If (as looks likely) XPath 2.0 keeps its current for expressions,
you could alternatively create a named sort specification:

<xsl:sort-key name="computers">
  <xsl:sort select="@version" />
  <xsl:sort select="@name" />
</xsl:sort-key>

and then tuck it all up inside a single XPath and take an XQuery-like
approach instead:

  <xsl:copy-of select="
    sort('computers',
         for $tool in tool,
             $release in $sw-file/key('releasekey',
                                      concat($tool/@name, '#',
                                             $tool/@version)),
             $computer in $hw-file/key('hw_key', $release/computer/@name)
         return $computer)" />

Cheers,

Jeni

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]