Reputation: 1979
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
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
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
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
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