Filtering on multiple params in XSL

Gertone helped me a lot with this and I thought I had it, but I'm still stumped.  I'm trying to use XSL to filter on multiple elements from the following XML file.  

<NODES>
  <APPLICANT>
    <NAME>Sean McGowan</NAME>
    <PREFERRED></PREFERRED>
    <FLAGGED>1</FLAGGED>
  </APPLICANT>
  <APPLICANT>
    <NAME>Carol Gillette</NAME>
    <PREFERRED>1</PREFERRED>
    <FLAGGED></FLAGGED>
</NODES>
 
I'm passing parameters to XSL with the names of the elements I want to match and the values they should match.  The hard part is that I want a rows to display whenever EITHER of the filter elements matches the desired value.   Here are the params:

  <xsl:param name="filter1" />
  <xsl:param name="filter1value" />
  <xsl:param name="filter2" />
  <xsl:param name="filter2value" />

And here is my select statement:

<xsl:for-each select="//APPLICANT[
         *      [(name() = $filter1 and . = $filter1value) or (string-length($filter1) = 0)]
                [(name() = $filter2 and . = $filter2value) or (string-length($filter2) = 0)]
]">

I pass the parameters $filter1 = "FLAGGED" &  $filter1value = "1", for example.
This works fine when either of the parameters are set, but returns no rows when both are set by passing $filter2 = "PREFERRED" &  $filter2value = "1", too .  I could use an OR statement instead, such as:

<xsl:for-each select="//APPLICANT[
         *      [(name() = $filter1 and . = $filter1value) or (string-length($filter1) = 0)]
         |*    [(name() = $filter2 and . = $filter2value) or (string-length($filter2) = 0)]
]">

But this returns true for all rows when one of the parameters isn't set.  I need to be able to filter on either or both parameters.  I think the problem with the AND method is that the name() function is looking at the XML elements one at a time.  If name() = $filter1 in the first predicate, it won't in the second.  What can I do?
LVL 2
etd_onlineguysAsked:
Who is Participating?
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.

Geert BormansInformation ArchitectCommented:
is this what you want

<xsl:for-each select="//APPLICANT[
         *     [(name() = $filter1 and . = $filter1value) and not(string-length($filter1) = 0)]
         |*    [(name() = $filter2 and . = $filter2value) and not(string-length($filter2) = 0)]
]">
0
Geert BormansInformation ArchitectCommented:
etd_onlineguys,

ignore my previous suggestion

I think we have to break tis stuff apart to really see what you need
so if I go wrong somewhere, just tell me

for only one filter this would work
            select="//APPLICANT[
            *[(name() = $filter1 and . = $filter1value) or (string-length($filter1) = 0)]
            ]">
applicants would be selected if $filter1 was given the matching value
or when the filter would be left open

the problem arises when you use two filters
one filter would be selective and the other not, leading to no filtering
so we have to disable the empty filter test, if one of the other filters is set

would be something like this
           select="//APPLICANT[
             *[(name() = $filter1 and . = $filter1value) or ((string-length($filter1) = 0) and (string-length($filter2) = 0))]
            ]">

with two filters this works
        <xsl:for-each
            select="//APPLICANT[
            *[(name() = $filter1 and . = $filter1value) or ((string-length($filter1) = 0) and (string-length($filter2) = 0))]
          |  *[(name() = $filter2 and . = $filter2value) or ((string-length($filter1) = 0) and (string-length($filter2) = 0))]
            ]">

now maybe you want to have three filters
this can become clumsy, but we can rewrite this
because basically if no filter is passed, you want to select all the rows, otherwise you apply the filters

        <xsl:for-each
            select="//APPLICANT[
            *[(name() = $filter1 and . = $filter1value)]
          |  *[(name() = $filter2 and . = $filter2value)]
            | * [(string-length($filter1) = 0) and (string-length($filter2) = 0)]
            ]">

does that job and is pretty extensible

Now I am not sure about having two filters specified
    <xsl:param name="filter1" >NAME</xsl:param>
    <xsl:param name="filter1value" >Sean McGowan</xsl:param>
    <xsl:param name="filter2" >PREFERRED</xsl:param>
    <xsl:param name="filter2value" >2</xsl:param>

do you want all the applicants that have the name Sean... plus all the applicants that have a preferred of 2 (union)
the above solution would give you that

if you want all the applicants that have the name Sean... and  a preferred of 2 (intersection)
you need this

        <xsl:for-each
            select="//APPLICANT[
           *[name() = $filter1] = $filter1value and *[name() = $filter2] = $filter2value
            or *[name() = $filter1] = $filter1value and (string-length($filter2) = 0)
            or *[name() = $filter2] = $filter2value and (string-length($filter1) = 0)
            or ((string-length($filter1) = 0) and (string-length($filter2) = 0))
            ]">

and that is a bit less extensible, but still OK for three if you want

cheers

Geert


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
etd_onlineguysAuthor Commented:
Geert,
I thank you for this elegant and extensible solution.  You make it look easy.
David
0
Geert BormansInformation ArchitectCommented:
you are welcome David
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.