Filtering on multiple params in XSL

Posted on 2006-04-20
Last Modified: 2012-05-05
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.  

    <NAME>Sean McGowan</NAME>
    <NAME>Carol Gillette</NAME>
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?
Question by:etd_onlineguys
    LVL 60

    Expert Comment

    by:Geert Bormans
    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)]
    LVL 60

    Accepted Solution


    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
                *[(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
                 *[(name() = $filter1 and . = $filter1value) or ((string-length($filter1) = 0) and (string-length($filter2) = 0))]

    with two filters this works
                *[(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

                *[(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

               *[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



    LVL 2

    Author Comment

    I thank you for this elegant and extensible solution.  You make it look easy.
    LVL 60

    Expert Comment

    by:Geert Bormans
    you are welcome David

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Why You Should Analyze Threat Actor TTPs

    After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

    Introduction In my previous article ( I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
    I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
    Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
    Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

    737 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    22 Experts available now in Live!

    Get 1:1 Help Now