XSLT value for State should match list of States, AL, AK,AZ,AR,CA, etc.

I am trying to add some code to my xsl stylesheet that will check the value (in the XML) for the "State" node and if it doesn't match the list of states, I will show an error message in the html output.
rcheneyAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rcheneyAuthor Commented:
How do I go about comparing the users input for the "State" value against a list of all the acceptable two-letter values for the fifty states?  Do I do this with template-match type of thing or with contains($State, "AK|AL|CA|MN")  etc.
Or is there something with Match? or pattern match?   I have the list of states and I can compare the State value with one state at a time.  Should I use some sort of   for-each  statement?
Thanks in advance for any clues pointing me in the right general direction.
0
dualsoulCommented:
>Do I do this with template-match type of thing or with contains($State, "AK|AL|CA|MN")  
if it suite you , why not? i think it's the most straightforward and simple way.

<xsl:for-each select="user[@State='AK|AL|CA|MN']> - will select all users with state within AK AL CA MN
assuming you have xml like this:
       <user State="AK">
..............

also you can use extension-function, written in some language like Java, that will do comparsion.

0
rcheneyAuthor Commented:
contains($State, "AK|AL|CA|MN") doesn't work because the "pipe" separator is not recognized as meaning "or".  It just looks at the entire AK|AL|CA|MN as one block of text to search the string for.

Will    for-each  cycle through node 'values'  or just the nodes themselves?  As I am processing each "State" node, I need to check the value to see if it matches AK|AL|CA|MN   etc.
0
OWASP: Threats Fundamentals

Learn the top ten threats that are present in modern web-application development and how to protect your business from them.

dualsoulCommented:
contains() - hm...i don't remember wha't this? one of XPath function?
i mean your own extension-function, not one from XSLT


>Will    for-each  cycle through node 'values'  or just the nodes themselves?  As I am processing each "State" node, I >need to check the value to see if it matches AK|AL|CA|MN   etc.

so i assuming you are using somethink like this (or post your code here):

<xsl:template match="State">
..................................
<!-- test for State value -->
         <xsl:if test=".='AK|AL|CA|MN'">
                     ....test match....
         </xsl:if>
</xsl:template>

0
rcheneyAuthor Commented:
I tried the code below, but not in a template, just in the middle of my xsl stylesheet when processing the node. It works if the value for the node is AK and I only have ='AK' but when I add more states example: ='AK|AL|MN',  it doesn't look at it as AK or AL or MN it just seems to think I am checking for a string like "AK|AL|MN".   Would it work differently if I do the checking in a template, instead of the way I am doing it?  

<xsl:if test="ownershipDocument/reportingOwner/reportingOwnerAddress/rptOwnerState='MN|AK'">
                     ....test match....
         </xsl:if>
0
rcheneyAuthor Commented:
I just tried using "or" instead of the "pipe" character and it looks like it might work.

..........Instead of...........
<xsl:if test="ownershipDocument/reportingOwner/reportingOwnerAddress/rptOwnerState='MN|AK'">
                ....test match....
</xsl:if>

............like this instead............. with   'or'

<xsl:if test="ownershipDocument/reportingOwner/reportingOwnerAddress/rptOwnerState='MN' or 'AK' or 'AL'">
                     ....test match....
         </xsl:if>
0
rcheneyAuthor Commented:
I was wrong, 'AK' or 'AL'    etc.  does not work.  It just reports a "match" even if the State value does not match the list.
0
dualsoulCommented:
or sorry....
insted of : test=".='AK|AL|CA|MN'", try this:

   test= ".='AK'|'AL'|'CA'|'MN'"

0
PeterCiuffettiCommented:
The contains goes the other way.  You want to look for your state in a list of known state values this way.  Put it in a variable, put delimiters on it and then check...

contains('|AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|',concat('|',$theState,'|'))

Here's a solution that corrects case, checks length and returns a message indicating valid or not.  Given the test document...

<test>
      <state>MA</state>
      <state>Me</state>
      <state>AK</state>
      <state>A</state>
      <state>Al</state>
      <state>AX</state>
      <state>AZ</state>
</test>

And the stylesheet...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="test">
      <result>
            <xsl:for-each select="state">
                  <state>
                        <xsl:call-template name="checkState">
                              <xsl:with-param name="theState" select="translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQURSTUVWXYZ')"/>
                        </xsl:call-template>
                  </state>
            </xsl:for-each>
      </result>
</xsl:template>

<xsl:template name="checkState">
      <xsl:param name="theState"/>

      <xsl:choose>
            <xsl:when test="string-length($theState) != 2">
                  <xsl:value-of select="$theState"/>
                  <xsl:text> is not a valid state abbreviation</xsl:text>
            </xsl:when>
            <xsl:when test="contains('|AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|',concat('|',$theState,'|'))">
                  <xsl:value-of select="$theState"/>
                  <xsl:text> is a valid state abbreviation</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                  <xsl:value-of select="$theState"/>
                  <xsl:text> is not a valid state abbreviation</xsl:text>
            </xsl:otherwise>
      </xsl:choose>
</xsl:template>

</xsl:stylesheet>

It will produce the following output...

<result>
  <state>MA is a valid state abbreviation</state>
  <state>ME is a valid state abbreviation</state>
  <state>AK is a valid state abbreviation</state>
  <state>A is not a valid state abbreviation</state>
  <state>AL is a valid state abbreviation</state>
  <state>AX is not a valid state abbreviation</state>
  <state>AZ is a valid state abbreviation</state>
</result>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rcheneyAuthor Commented:
Thank You Peter, for the fabulous answer.  It took me awhile to respond because it took me awhile to adjust the code to fit my existing stylesheet and then test it.  I am just starting to figure out how to use templates and template-match, etc.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
XML

From novice to tech pro — start learning today.