Anonymous
Anonymous

Reputation: 1979

XSL conditional nightmare

I have a really long 'or' conditional in XSL that works but it's completely ugly. When I receive an order, depending on which state the order is from a different product is opened. What would be the best way of slimming this down? Any help would be appreciate.

($document_Input_1/OrderInfo/foo/bar/state)=('AZ') 
 or ($document_Input_1/OrderInfo/foo/bar/state)=('CO')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('CT')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('DC')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('IL')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('KY')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('LA')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MA')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MD')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('ME')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MI')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MN')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MO')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MS')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('MT')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('NE')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('NV')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('OH')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('RI')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('SC')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('TN')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('VA')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('WI')  
 or ($document_Input_1/OrderInfo/foo/bar/state)=('WV')">

Upvotes: 2

Views: 116

Answers (4)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25034

In XSLT 2.0, a simpler way to write this is:

 $document_Input_1/OrderInfo/foo/bar/state
 = 
 ('AZ', 'CO', 'CT', 'DC', 'IL', 'KY', 
  'LA', 'MA', 'MD', 'ME', 'MI', 'MN', 
  'MO', 'MS', 'MT', 'NE', 'NV', 'OH', 
  'RI', 'SC', 'TN', 'VA', 'WI', 'WV')

In XSLT 1.0 (and 2.0, for that matter), you might put the relevant information in an external document (call it states.xml) with a structure like this:

<states>
  <group product="P1">
    <state id="AK"/>
     ...
  </group>
  <group product="P2">
    <state id='AZ'/>
    <state id='CO'/>
    ...
    <state id='WI'/>
    <state id='WV'/>
  </group>
</states>

Now your expression might be

$document_Input_1/OrderInfo/foo/bar/state
= 
document('states.xml')
//group[@product='P2']/state/@id

Or if the states are grouped in many different ways, it may be simpler to organize states.xml like this:

<states>
  <state id="AK" product="P1"/>
  <state id="AL" product="P1"/>  
  <state id='CO' product="P2"/>
  <state id='CT' product="P2"/>
  ...
  <state id='WV' product="P2"/>
</states>

Now you can express your condition as

$document_Input_1/OrderInfo/foo/bar/state
= 
document('states.xml')
//state[@product='P2']/@id

Upvotes: 4

michael.hor257k
michael.hor257k

Reputation: 116959

If you're looking only to streamline your existing approach, then you could use something like:

<xsl:variable name="product1" select="'-AZ-CO-CT-DC-IL-KY-LA-MA-MD-ME-MI-MN-MO-MS-MT-NE-NV-OH-RI-SC-TN-VA-WI-WV-'" />
<xsl:variable name="product2" select="'-AK-DE-FL-GA-HI-ID-IL-IA-OR-PA-SD-WY-'" />
<xsl:variable name="product3" select="'-AR-CA-CO-IN-KS-LA-MH-NH-OK-'" />
<xsl:variable name="state" select="concat('-', $document_Input_1/OrderInfo/foo/bar/state, '-')" />

<xsl:choose>
    <xsl:when test="contains($product1, $state)">product1</xsl:when>
    <xsl:when test="contains($product2, $state)">product2</xsl:when>
    <xsl:when test="contains($product3, $state)">product3</xsl:when>
    ...
</xsl:choose>

However, I would urge you to consider keeping a state-to-product lookup table in XML format, as suggested by C. M. Sperberg-McQueen.

Upvotes: 1

terrywb
terrywb

Reputation: 3956

Option 1, simplify the XPATH

<xsl:variable name="test" select="$document_Input_1/OrderInfo/foo/bar/state/text()"/>
<xsl:if test="$test='AZ' or $test='CO' ...">

Option 2, test for each state in an xsl:choose

<xsl:variable name="test" select="$document_Input_1/OrderInfo/foo/bar/state/text()"/>
<xsl:variable name="result">
  <xsl:choose>
     <xsl:when test="$test='AZ'>1</xsl:when>
     <xsl:when test="$test='CO'>1</xsl:when>
     ...
  </xsl:choose>

Option 3, create a named template to test for each state perhaps returning some other useful value like a tax rate.

Upvotes: 2

gmiley
gmiley

Reputation: 6604

You could do something similar to the following. It might only slightly unclutter what you have.

<xsl:for-each select="$document_Input_1/OrderInfo/foo/bar/state">
 <xsl:if test="text() = 'AZ' or
            text() = 'CO' or
            text() = 'CT' or
            text() = 'DC'">     
  <!-- do whatever -->
 </xsl:if>
</xsl:for-each>

Upvotes: 1

Related Questions