[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] xsl:key, multiple conditions on sub elements


Subject: [xsl] xsl:key, multiple conditions on sub elements
From: "Fredrik Bergholtz" <fredrik.bergholtz@xxxxx>
Date: Fri, 28 Oct 2005 23:17:25 +0200

Hello, I am hoping that somebody can help me with a little XSLT "key"
problem.
 
What I want to do is to select elements from an UML model (encoded as
XMI from 
Enterprise Architect) based on associations. What I have is a number of
classes that
have associations to other classes and for each class I want to select
all other
classes that has an association with the current class. 
 
Consider this list of associations:
 
message-set          -> road_traffic_message
road_traffic_message -> accidents
road_traffic_message -> obstructions
 
When the current element is "road_traffic_message" I want to select
"accidents" and
"obstructions" but not "message_set".
 
I will use an attribute named "aggregation" to determine if the class
should be 
included or not. I know that this isn't the best way to do this, but it
should work.
I verified the XMI to make sure that my condition holds. The
association ends on the
left side of my list above has the value "shared" while the ones to the
right have
the value "none".
 
In the template for a class I use this to find all the associated
classes:
 
<xsl:apply-templates select="key('childassociations', @...)"/>
 
My first attempt for the key looks like this:
 
<xsl:key name="childassociations"
match="//UML:Association[UML:Association.connection/UML:AssociationEnd/@aggregation='shared']"
use="UML:Association.connection/UML:AssociationEnd/@type"/>
 
In the template for associations I plan to recursively apply the
template for 
classes. Currently I only list some parameters to see what it does.
 
What I notice is that it, correctly, matches elements such as these:
 
<UML:Association xmi.id="EAID_1180618B_12CD_460b_BD47_F02F32DFCF78"
visibility="public" isRoot="false" isLeaf="false" isAbstract="false">
 <UML:Association.connection>
  <UML:AssociationEnd visibility="public" multiplicity="0..*"
aggregation="none" isOrdered="false" isNavigable="true"
type="EAID_C6F1867B_2E01_4091_A1B7_6145F61619F2"/>
  <UML:AssociationEnd visibility="public" multiplicity="0..1"
aggregation="shared" isOrdered="false" isNavigable="false"
type="EAID_4FD7F248_DE4C_49ed_B3F3_B1AFD271A6A1"/>
 </UML:Association.connection>
</UML:Association>
 
But it also matches elements such as these:
 
<UML:Association xmi.id="EAID_585000A5_57C8_4de1_9EEB_864586879F61"
visibility="public" isRoot="false" isLeaf="false" isAbstract="false">
 <UML:Association.connection>
  <UML:AssociationEnd visibility="public" multiplicity="0..*"
aggregation="none" isOrdered="false" targetScope="instance"
isNavigable="true" type="EAID_4FD7F248_DE4C_49ed_B3F3_B1AFD271A6A1"/>
  <UML:AssociationEnd visibility="public" multiplicity="0..1"
aggregation="shared" isOrdered="false" targetScope="instance"
isNavigable="false" type="EAID_27008050_00CA_4242_ADC5_91B1F36ED4BD"/>
 </UML:Association.connection>
</UML:Association>
 
The xmi.id for "road_traffic_message" is
"EAID_4FD7F248_DE4C_49ed_B3F3_B1AFD271A6A1".
 
I assume that the logical error here is that it first checks the
condition for the 
"aggregation" attribute and determines that, yes there is such a child
element within 
this "Association" element. Then it checks the condition for the "type"
attribute 
and determines that, yes we also have a child element such as this
within this 
"Association" element. What happened was that the two checks were not
connected - 
they matched different child elements. 
 
Is there a way to make the key select only "Associations" that have 
aggregation="shared" and type="xxx" in the _same_ child element of the
"Association"?
 
In other terms, I get this:
 
(exists (child element with aggregation="shared")) and (exists (child
with type="x"))
 
but I want this:
 
exists (child with (aggregation="shared" and type="x"))
 

Kind Regards,
Fredrik Bergholtz


Current Thread
Keywords