سؤال

لدي بعض الخبرة مع XSLT ولكن الآن لدي مشكلة في نفسي: أحتاج إلى التحقق مما إذا كانت فترة بين البدء والإنجاز تغطي فترة أخرى تماما.

إليك جزء من 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>

لذلك أحتاج إلى التحقق مما إذا كانت الفترة بين بداية وتنتهي الوالد مغطاة بالكامل بفترة ما بين بداية ونهاية الطفل في XSLT واكتب الوالد ومعرف الطفل إلى XML لفشله.

هل يمكن لشخص ما أن يعطيني رأسا يبدأ كيفية إدارة هذا في XSLT ...؟

لدي التحكم الكامل في بنية XML، لذلك عندما يكون الأمر أسهل مع بنية XML الأخرى (مع نفس البيانات)، يمكنني تغييره.

شكرا جزيلا!

هل كانت مفيدة؟

المحلول

باستخدام مقارنة سلسلة بسيطة هذا سهل، لأن تنسيق التاريخ الخاص بك هو الإندان الكبير. فيما يلي وثيقة XSLT سريعة كتبت لاختبارها:

<?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>

من الواضح أنك ستحتاج إلى الشيكات الخاصة بك للتأكد من ذلك StartDate قبل ذلك EndDate لكل من الوالد والطفل.

نصائح أخرى

فيما يلي مثال للقيام بذلك مباشرة في XSLT 2.0 وينبغي أن يعمل مع معظم DEMIMETERS:

    <?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>

ما المشكلة في number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)?

هذا لن يحل محل كامل، ولكن قد ترغب في التحقق من ملحقات Exslt لتاريخ التاريخ، هنا.

ومع ذلك، أفكر في إنشاء زوجين XSLT تمديد وظائف, ، استخدام جودا وقت التجريدات الفاصلة. وبعد ربما بطريقة أسهل وأسرع من محاولة القيام بذلك من XSLT مباشرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top