xsl-list
[Top] [All Lists]

RE: [xsl] Ways to simplify XSL, complex "select/filter criteria"

2009-12-18 05:24:00

I don't think I fully understand the requirement, but it's certainly a case
where your code can be simplified by use of functions. For example you can
define this function

<xsl:function name="f:applies-now" as="xs:boolean">
  <xsl:param name="v" as="element(ns:validFor)"/>
  <xsl:variable name="start" as="xs:dateTime?"
    select="xs:dateTime($v/ns:startDateTime)"/>
  <xsl:variable name="end" as="xs:dateTime?"
    select="xs:dateTime($v/ns:endDateTime)"/>
  <xsl:sequence select="(empty($start) or $start le current-dateTime()) and
                         (empty($end) or $end ge current-dateTime()))"/>
</xsl:function>

and this one

<xsl:function name="f:type" as="xs:QName">
  <xsl:param name="e" as="element()"/>
  <xsl:sequence select="QName($e/@xsi:type, $e)"/>
</xsl:function>

and then you can do things like

<xsl:value-of select="/cdm:Individual/cdm:PartyPlays
                           [f:type(.) eq xs:QName("fn:Employee")]
                           [exists(ns:validFor[f:applies-now(.)])]"/>

Regards,

Michael Kay
http://www.saxonica.com/
http://twitter.com/michaelhkay 

-----Original Message-----
From: Stefan Fritz [mailto:sfritz(_dot_)nospam(_at_)gmx(_dot_)at] 
Sent: 18 December 2009 10:07
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] Ways to simplify XSL, complex "select/filter criteria"

Hi all,

first my environment: Saxon 8.9, XSL and Xpath 2.0, Java

I have to transform a XML document which contains elements 
with the same name but different xs:type.
In addition the elements contain an optional validFor element 
which defines a time period for the validity of the data.

The rules to implement is:
- select element by xsi type
- select the valid (in time period) element
- if no time period specified and multiple elements of the 
same type exist, take the first one

I have to apply these rules in almost every value-of 
selection in my XSLT and therefore the XSLT became really a nightmare.
I hope there is a solution to simplify this. I though about 
xsl:function, dynamic Xpath (saxon:evaluate,..) but couldn't 
get it to work.
Any help more than appreciated!

Thanks
Stefan

simplified XML and XSL:

<ns:Individual
xsi:type="ns:Individual"
xmlns:ns="http://myns";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

<ns:validFor xsi:type="ns:TimePeriod">
<ns:startDateTime>1800-01-01T00:00:00</ns:startDateTime>
<ns:endDateTime/>
</ns:validFor>

<ns:PartyPlays xsi:type="ns:Employee">
<ns:validFor xsi:type="ns:TimePeriod">
<ns:startDateTime>2005-09-19T00:00:00</ns:startDateTime>
<ns:endDateTime/>
</ns:validFor>
<ns:PartyRoleContactableVia xsi:type="ns:PostalContact">
                 ...
</ns:PartyRoleContactableVia>
<ns:PartyRoleContactableVia xsi:type="ns:PostalContact">
             ...
</ns:PartyRoleContactableVia>
<ns:PartyRoleContactableVia xsi:type="ns:EMailContact"> 
<ns:validFor xsi:type="ns:TimePeriod"> 
<ns:endDateTime>2010-09-19T00:00:00</ns:endDateTime>
</ns:validFor>
<ns:eMailAddress>email1(_at_)my(_dot_)com</ns:eMailAddress>
</ns:PartyRoleContactableVia>
<ns:PartyRoleContactableVia xsi:type="ns:EMailContact"> 
<ns:validFor xsi:type="ns:TimePeriod"> 
<ns:endDateTime>2010-09-19T00:00:00</ns:endDateTime>
</ns:validFor>
<ns:eMailAddress>email2(_at_)my(_dot_)com</ns:eMailAddress>
</ns:PartyRoleContactableVia>
</ns:PartyPlays>
</ns:Individual>


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
xmlns:cdm="http://myns"; 
xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
<xsl:output method="text"/>

<xsl:template match="/">
<xsl:value-of
select="/cdm:Individual/cdm:PartyPlays[contains(@xsi:type,'Emp
loyee')][
if(string-length(cdm:validFor/cdm:startDateTime) gt 0 and
string-length(cdm:validFor/cdm:endDateTime) gt 0) then
(xs:dateTime(cdm:validFor/cdm:startDateTime) lt 
current-dateTime() and 
xs:dateTime(cdm:validFor/cdm:endDateTime)gt 
current-dateTime()) else 
if(string-length(cdm:validFor/cdm:startDateTime) gt 0) then
(xs:dateTime(cdm:validFor/cdm:startDateTime) lt 
current-dateTime()) else 
if(string-length(cdm:validFor/cdm:endDateTime) gt 0) then ( 
xs:dateTime(cdm:validFor/cdm:endDateTime)gt current-dateTime()) else
1
]/cdm:PartyRoleContactableVia[contains(@xsi:type,'EMailContact')][
if(string-length(cdm:validFor/cdm:startDateTime) gt 0 and
string-length(cdm:validFor/cdm:endDateTime) gt 0) then
(xs:dateTime(cdm:validFor/cdm:startDateTime) lt 
current-dateTime() and 
xs:dateTime(cdm:validFor/cdm:endDateTime)gt 
current-dateTime()) else 
if(string-length(cdm:validFor/cdm:startDateTime) gt 0) then
(xs:dateTime(cdm:validFor/cdm:startDateTime) lt 
current-dateTime()) else 
if(string-length(cdm:validFor/cdm:endDateTime) gt 0) then ( 
xs:dateTime(cdm:validFor/cdm:endDateTime)gt current-dateTime()) else
1
][1]/cdm:eMailAddress[1]"/>
</xsl:template>
</xsl:stylesheet>



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>