Question

J'ai une certaine expérience avec XSLT, mais maintenant je l'ai moi-même eu un problème: Je dois vérifier si une période entre un BEGIN et endDate couvre complètement une autre période.

Voici une partie du 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>

Alors je dois vérifier si la période entre le début et la fin du parent est entièrement couvert par la période entre le début et la fin de l'enfant en XSLT et écrire le parent et l'ID enfant de XML pour échoue.

Quelqu'un peut-il me donner un bon départ comment gérer ce XSLT ...?

J'ai un contrôle total sur la structure du XML ainsi quand il est plus facile avec une autre structure XML (avec les mêmes données) je peux changer.

Merci beaucoup!

Était-ce utile?

La solution

Utilisation simple comparaison de chaînes cela est facile, parce que votre format de date est grand-boutiste. Voici un document XSLT rapide je l'ai écrit à le tester:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <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>

vous avez besoin Il est évident que vos propres chèques pour vous assurer que StartDate est avant EndDate pour les parents et les enfants.

Autres conseils

Voici un exemple pour le faire directement dans xslt 2.0 et devrait fonctionner avec la plupart Date délimiteurs:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0"
            exclude-result-prefixes="functx xs"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:functx="http://www.functx.com"
            xmlns:xs="http://www.w3.org/2001/XMLSchema">

        <xsl:template match="/">
            <dates>
                <dateBetween>
                    <xsl:choose>
                        <xsl:when test="functx:dateBetween('02-01-2009','01-01-2009','03-01-2009')=true()">
                            <xsl:text>date lays between given dates</xsl:text>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:text>date is not between given dates</xsl:text>
                        </xsl:otherwise>
                    </xsl:choose>
                </dateBetween>
                <currentDateBetween>
                    <xsl:choose>
                        <xsl:when test="functx:currentDateBetween('01-01-2000','01-01-2019')=true()">
                            <xsl:text>current date lays between given dates</xsl:text>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:text>current date is not between given dates</xsl:text>
                        </xsl:otherwise>
                    </xsl:choose>
                </currentDateBetween>
            </dates>
        </xsl:template>

         <!-- 
            Function:       dateBetween
            Description:    This function will check if a dates is between given dates
            Input:          Input date, Input start date, Input end date
            Output:         Boolean true if beween param 2 and 3
            Created:        21-09-2012 by Raymond Meester
        -->
        <xsl:function name="functx:dateBetween">
            <xsl:param name="param1"/>
            <xsl:param name="param2"/>
            <xsl:param name="param3"/>

            <xsl:variable name ="dateToCheck" select="functx:mmddyyyy-to-date($param1)"/>        
            <xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param2)"/>
            <xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param3)"/>    
            <xsl:variable name ="true" as="xs:boolean" select="true()"/>
            <xsl:variable name ="false" as="xs:boolean" select="false()"/>          

            <xsl:choose>
                <xsl:when test="$startDate &lt; $dateToCheck and $dateToCheck &lt; $endDate"><xsl:value-of select="$true"/></xsl:when>
                <xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise>
            </xsl:choose>

        </xsl:function>

        <!-- 
            Function:       currentDateBetween
            Description:    This function will check if a dates is between given dates
            Input:          Input date, Input start date, Input end date
            Output:         Boolean true if beween param 2 and 3
            Created:        21-09-2012 by Raymond Meester
        -->    
        <xsl:function name="functx:currentDateBetween">
            <xsl:param name="param1"/>
            <xsl:param name="param2"/>

            <xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param1)"/>
            <xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param2)"/>    
            <xsl:variable name ="true" as="xs:boolean" select="true()"/>
            <xsl:variable name ="false" as="xs:boolean" select="false()"/>          

            <xsl:choose>
                <xsl:when test="$startDate &lt; current-date() and current-date() &lt; $endDate"><xsl:value-of select="$true"/></xsl:when>
                <xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise>
            </xsl:choose>

        </xsl:function>

        <!-- 
            Function:       mmddyyyy-to-date
            Description:    The functx:mmddyyyy-to-date function converts $dateString into a valid xs:date value. The order of the digits in $dateString must be MMDDYYYY, but it can contain any (or no) delimiters between the digits.
            Input:          Input string
            Output:         Return date
            Created:        2007-02-26 http://www.xsltfunctions.com/xsl/functx_mmddyyyy-to-date.html
        -->      
        <xsl:function name="functx:mmddyyyy-to-date" as="xs:date?"
                xmlns:functx="http://www.functx.com">
            <xsl:param name="dateString" as="xs:string?"/>
            <xsl:sequence select="if (empty($dateString)) then () else if (not(matches($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$'))) then error(xs:QName('functx:Invalid_Date_Format')) else xs:date(replace($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$','$3-$1-$2'))"/>
        </xsl:function>

    </xsl:stylesheet>

Qu'est-ce qui ne va pas avec number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)?

Ce ne va pas à une solution complète, mais vous pouvez vérifier les extensions EXSLT pour la manipulation de ce jour, fonctions d'extension XSLT , en utilisant abstractions Intervalle de temps Joda . Probablement plus facile et plus rapide que d'essayer de le faire à partir XSLT directement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top