Joachim Hollekim
Joachim Hollekim

Reputation: 39

Filtering users from XML with XSL based on date?

I have a routine where I assign memberships to users based on data from a XML-file. However, the source has recently introduced timeframe into the memberships and I now need to filter based on active timeframe. Sounds easy, right?

However:

  1. Some users don't have a timeframe. They must not be filtered.
  2. Some users have 2 timeframes, where one, both or none may be active. Those with one or both timeframes active must be selected
  3. Some users have timeframes with begin but not end. They must be selected if current date is after begin date.

Here's an example:

<member>
<sourcedid>
<id>person_0f2f2d24-c19a-42d8-98bd-2f4147d693a60</id>
</sourcedid>
<idtype>1</idtype>
<role roletype="01">
<status>0</status>
<datetime>2020-08-01</datetime>
<timeframe>
<begin restrict="0">2020-08-01</begin>
<end restrict="0">2020-08-21</end>
<adminperiod>H2020/V2021</adminperiod>
</timeframe>
</role>
<role roletype="01">
<status>1</status>
<datetime>2020-08-22</datetime>
<timeframe>
<begin restrict="0">2020-08-22</begin>
<end restrict="0">2021-07-31</end>
<adminperiod>H2020/V2021</adminperiod>
</timeframe>
</role>
</member>

We tried this, but it only works on those with 1 timeframe:

<xsl:for-each select="$sections">
                <xsl:variable name="group" select="."/>
                <xsl:variable name="memberships" select="key('membership', $group/sourcedid/id, $root)"/>
                <xsl:for-each select="$memberships">
                    <xsl:variable name="membership" select="."/>
                    <xsl:for-each select="$membership/member[role[@roletype eq '01']][my:filterMember(.)]">
                        <xsl:value-of select="$membership/sourcedid/id"/><xsl:value-of select="$delimiter"/>
                        <xsl:value-of select="sourcedid/id"/><xsl:value-of select="$break"/>
                    </xsl:for-each>
                </xsl:for-each>
</xsl:for-each>

    <xsl:function name="my:filterMember">
        <xsl:param name="member"/>
        <xsl:variable name="timeframes" select="$member/role/timeframe"/>
        <xsl:choose>
            <xsl:when test="$timeframes[begin/xs:date(.) gt current-date() or end/xs:date(.) lt current-date()]">
                <xsl:sequence select="false()"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="true()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

Any suggestions?

Upvotes: 0

Views: 118

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117073

Couldn't you do simply:

select="member[some $timeframe in role/timeframe satisfies $timeframe/xs:date(begin) le current-date() and ($timeframe/xs:date(end) gt current-date() or not($timeframe/end))]"

This should implement your 2nd and 3d condition. I did not understand your 1st condition: it can be read both ways. If "not filtered" means "included in the selection", then just add or not(role/timeframe).

Upvotes: 2

Related Questions