views:

351

answers:

3

Hi there,

I have some experience with XSLT but now i've got myself a problem: I need to check if a period between a begin- and enddate completely covers an other period.

Here's a part of the xml:

<Parent ID="1">
  <StartDate>20050101</StartDate>
  <EndDate>20060131</EndDate>
  <Child ID="1">
    <StartDate>20050101</StartDate>
    <EndDate>20081231</EndDate>
  </Child>
</Parent>
<Parent ID="2">
  <StartDate>20060201</StartDate>
  <EndDate>20071231</EndDate>
  <Child ID="1">
    <StartDate>20050101</StartDate>
    <EndDate>20081231</EndDate>
  </Child>
</Parent>
<Parent ID="3">
  <StartDate>20080101</StartDate>
  <EndDate>20081231<EndDate>
  <Child ID="1">
    <StartDate>20050101</StartDate>
    <EndDate>20081231</EndDate>
  </Child>
</Parent>

So i need to check if the period between start and end of the Parent is fully covered by the period between start and end of the Child in XSLT and write the Parent and Child ID's to xml for fails.

Can someone give me a head start how to manage this in XSLT...?

I have full control over the structure of the XML so when it's easier with an other XML structure (with the same data) i can change it.

Thanks a lot!

A: 

What's wrong with number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)?

Krab
+2  A: 

Using simple string comparison this is easy, because your date format is big-endian. Here's a quick XSLT document I wrote up to test it out:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="xml" version="1.0" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:for-each select="//Parent">
        <parent>
          <xsl:attribute name="id">
            <xsl:value-of select="@ID"/>
          </xsl:attribute>
          <xsl:choose>
            <xsl:when test="(Child/StartDate &lt;= StartDate) and 
              (Child/EndDate &gt;= EndDate)">
              <xsl:text>OK</xsl:text>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>Not OK</xsl:text>
            </xsl:otherwise>
          </xsl:choose>
        </parent>
      </xsl:for-each>
    </root>
  </xsl:template>
</xsl:stylesheet>

Obviously you'll need your own checks to make sure that StartDate is before EndDate for both parent and child.

Welbog
A few nitpicking remarks :) Doing `'//Parent'` is unnecessary, `'Parent'` is enough. `<xsl:attribute>` is redundant in favor of `<parent id="{@id}">`. Also, parentheses in the `<xsl:when>` test are not strictly necessary, though they increase readability.
Tomalak
@Tomalak: Like I usually tell you when you nitpick, I'm trying to explain something simply, to decrease the chances of getting people confused over syntax shorthand like `{@id}`. Though I'll give you the `//Parent` part. That was because I altered the original format slightly.
Welbog
A: 

This is not going to a complete solution, but you may want to check out the EXSLT extensions for date manipulation, here.

I would however consider creating a couple of XSLT extension functions, using Joda time's Interval abstractions. Probably way easier and faster than trying to do it from XSLT directly.

Wilfred Springer