Reputation: 188
I have an xml structure that looks like this:
<Person>
<ID> 123 </ID>
<Type> L </Type>
</Person>
<Person>
<ID> 456 </ID>
<Type> N </Type>
</Person>
<Person>
<ID> 123 </ID>
<Type> U </Type>
</Person>
Person is repeating, unlimited, but I only care about these 3 "types". I would like to somehow only select based on Type, but prioritize it, somehow.
I need to always choose the ID when type is L, regardless of what else is there. If L isn't there, choose N, and if N isn't there, U. Finally if U isn't there, don't output a node at all.
I've tried nested choose: (I apologize if this is syntactically incorrect, I'm manually typing to remove complexity.
<xsl:choose>
<xsl:when test = "Person/Type='L'>
<L-ID>
<xsl:value-of "Person[Type = 'L']/ID" />
</L-ID>
</xsl:when>
<xsl:otherwise>
<xsl:when test = "Person/Type='N'>
<N-ID>
<xsl:value-of "Person[Type = 'N']/ID" />
</N-ID>
</xsl:when>
<xsl:otherwise>
<xsl:when test = "Person/Type='U'>
<U-ID>
<xsl:value-of "Person[Type = 'U']/ID" />
</U-ID>
</xsl:when>
</xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
I've also thought of maybe using a combination of Ifs and Chooses but I can't quite wrap my head around the three conditions. I've tried mapping out truth tables, and just can't get it to do what I want.
If it helps, a table of what I want is this:
U | L | N | Output | XML
---+---+---+-----------+
1 1 1 L | <L-ID> 123 </L-ID>
1 1 0 L | <L-ID> 123 </L-ID>
1 0 1 N | <N-ID> 456 </N-ID>
1 0 0 U | <U-ID> 789 </U-ID>
0 1 1 L | <L-ID> 123 </L-ID>
0 1 0 L | <L-ID> 123 </L-ID>
0 0 1 N | <N-ID> 456 </N-ID>
0 0 0 Nothing |
Upvotes: 1
Views: 36
Reputation: 70598
The syntax for your xsl:choose
is this...
<xsl:choose>
<xsl:when test="Person/Type=' L '">
<L-ID>
<xsl:value-of select="Person[Type = ' L ']/ID" />
</L-ID>
</xsl:when>
<xsl:when test="Person/Type=' N '">
<N-ID>
<xsl:value-of select="Person[Type = ' N ']/ID" />
</N-ID>
</xsl:when>
<xsl:when test="Person/Type=' U '">
<U-ID>
<xsl:value-of select="Person[Type = ' U ']/ID" />
</U-ID>
</xsl:when>
</xsl:choose>
</xsl:template>
Do note the use of spaces in the check, as you have spaces around the letters in the type node; <Type> L </Type>
. An alternate way to write the xsl:when
tests would be this
<xsl:when test="Person[normalize-space(Type)= 'L']">
<L-ID>
<xsl:value-of select="Person[normalize-space(Type)= 'L']/ID" />
</L-ID>
</xsl:when>
Alternatively, you could take advantage of the fact the letters you want to select are in alphabetical order, so you can also do this..
<xsl:for-each select="Person[normalize-space(Type) = 'L' or normalize-space(Type) = 'N' or normalize-space(Type) = 'U']">
<xsl:sort select="Type" />
<xsl:if test="position() = 1">
<xsl:element name="{normalize-space(Type)}-ID">
<xsl:value-of select="ID" />
</xsl:element>
</xsl:if>
</xsl:for-each>
If you could use XSLT 2.0, you could simplify the xsl:for-each
to this...
<xsl:for-each select="Person[normalize-space(Type) = ('L', 'N', 'U')]">
Upvotes: 1