## Re: Problems with attributes.

 Subject: Re: Problems with attributes. From: Brandon Ibach Date: Wed, 20 Oct 1999 15:53:23 -0500
```   I'll start with the second message, as it contains the most
important point. :)

Quoting Reyes <reyes.garcia@xxxxxxxxxx>:
> One thing, I have tested more the procedure [ unique-son ], and I have
> looked that when there are two or more "ANKER" [ attributes ] successive
> works good.
>
> Also, if I have :
>                <WERK><SONW ANKER="#1"></SONW></WERK>
>                <WERK><SONW ANKER="#1"></SONW></WERK>
>                <WERK><SONW ANKER="#1COPIA"></SONW></WERK>
>                <WERK><SONW ANKER="#1COPIA"></SONW></WERK>
>
> the procedure works good, but if I have :
>
>                <WERK><SONW ANKER="#1"></SONW></WERK>
>                <WERK><SONW ANKER="#1COPIA"></SONW></WERK>
>                <WERK><SONW ANKER="#1"></SONW></WERK>
>                <WERK><SONW ANKER="#1COPIA"></SONW></WERK>
>
> the procedure doesn't work godd.
>
This is an excellent demonstration of the problem.  As you can see,
I've trimmed your examples down to just the important stuff.  The
problem has to do with your use of (list) to build up your "list of
ANKER values we've seen".  Let's walk through these two examples.
Your list-att (or son-list-att) starts as an empty list, so when
you call (member) with the first value, "#1", it will not find it,
thus list-att gets assigned the result of (list '() "#1"), which is
the list '(() "#1").  The next time through, (member) will find "#1"
in the list, so it will skip that SONW.  The third time, it won't find
"#1COPIA", so it will set list-att to '((() "#1") "#1COPIA").  The
fourth time, it will find "#1COPIA" and skip that SONW.
You can probably see what will happen with the second example.
Because the values being added to list-att are being nested inside
more lists, rather than being appended into one big list, the (member)
will only find a value if it was the last thing added.
Here's a somewhat different approach:

(define (unique-son node tag son att)
(let loop ((nl (select elements (descendants node) son))
(list-att '()) (result (empty-node-list)))
(if (node-list-empty? nl) result
(let* ((n (node-list-first nl)) (a (attribute-string att n)))
(if (member a list-att)
(loop (node-list-rest nl) list-att result)
(loop (node-list-rest nl) (cons a list-att)
(node-list result (ancestor tag n))))))))

Here, we just gather the list of "son" elements, filter it down
based on the "att" values, and construct a list of the ancestor "tag"
nodes for those which are selected.  This may need some modification
based on what, exactly, you want for results.  For instance, the same
"tag" (WERK) node could show up more than once in the result, if it
contained more than one unique "son" (SONW) element.
Notice how (cons) is used here.  Keep in mind that a list is really
a special type of pair.  A pair, such as (A . B), has a "car" (A) and
a "cdr" (B).  In a list, the cdr is always another pair, with the
final pair being the special "empty-list", ().  So, the list (A B C D
E) really looks like (A . (B . (C . (D . (E . ()))))).  Knowing that,
and the fact that (cons) takes two arguments and returns a pair in
which the car is the first argument, and the cdr is the second
argument, we see that the first argument to (cons) should be the new
item you want to add, and the second should be the list to which you
My turn... I hope *your* head doesn't hurt. :)

-Brandon :)

DSSSList info and archive:  http://www.mulberrytech.com/dsssl/dssslist

```