XSLT check values in for each and set value of element - xslt

I am not expert in XSLT. I have requirement to check all "code" values, set statuscode as per below rules.
If all code values are 200, then set statuscode to 200 and reasonphrase to success
If all code values are either 200 or 204, then set status code to 200 and reasonphrase is concatnatiopn of all reason which have code other than 200.
If atleast one code contains value other than 200 and 204, then set statuscode to 503 and reasonphrase is concatnatiopn of all reason which have code other than 200.
I have tried couple of ways which are to store all code values in one variable and execeute contains function with above conditions as well as create code variables and store values and then check string length. But i did not get any success.
I am looking for some more generic way if possible as this requirement is part of complex xslt and below is just an example of requirement.
Once i get logic for below code, i should be able to fit logic in complex xslt.
I also tried to search in answers but could not get any solution which fits this requirement.
I am looking for solution in xslt 1.0 as other part of xslt is written in xslt 1.0
Input -
<root>
<Node1>
<code>200</code>
<reason>Success</reason>
</Node1>
<Node1>
<code>200</code>
<reason>Success</reason>
</Node1>
<Node1>
<code>204</code>
<reason>Business Error</reason>
</Node1>
<Node1>
<code>500</code>
<reason>Tech Error</reason>
</Node1>
<Node1>
<code>200</code>
<reason>Success</reason>
</Node1>
</root>
Output-
<root>
<output>
<statuscode></statuscode>
<reasonphrase></reasonphrase>
</output>
</root>
Thank you.

Try this as your starting point:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:copy>
<output>
<xsl:choose>
<xsl:when test="not(Node1[code!=200])">
<!-- all code values are 200 -->
<statuscode>200</statuscode>
<reasonphrase>success</reasonphrase>
</xsl:when>
<xsl:when test="not(Node1[code!=200 and code!=204])">
<!-- all code values are either 200 or 204 -->
<statuscode>200</statuscode>
<reasonphrase>
<xsl:for-each select="Node1[code!=200]">
<xsl:value-of select="code"/>
<xsl:if test="position()!=last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</reasonphrase>
</xsl:when>
<xsl:otherwise>
<statuscode>503</statuscode>
<reasonphrase>
<xsl:for-each select="Node1[code!=200]">
<xsl:value-of select="code"/>
<xsl:if test="position()!=last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</reasonphrase>
</xsl:otherwise>
</xsl:choose>
</output>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that this could be streamlined to eliminate repeating code - but the point here is to show how to test for the given conditions.

Related

XSLT List attributes in the order they appear in the xml file

I have a large number of xml files with a structure similar to the following, although they are far larger:
<?xml version="1.0" encoding="UTF-8"?>
<a a1="3.0" a2="ABC">
<b b1="P1" b2="123">first
</b>
<b b1="P2" b2="456" b3="xyz">second
</b>
</a>
I want to get the following output:
1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3
where:
Field 1 is the sequence number for nodes /a/b
Field 2 is the sequence number of the attribute as it appears in the xml file
Field 3 is the attribute name (not value)
I don't quite know how to calculate field 2 correctly.
I've prepared the following xslt file:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:for-each select="a/b/#*">
<xsl:value-of select="count(../preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<!-- TODO: This is not correct -->
<xsl:value-of select="count(preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
but when I run the following command:
xsltproc a.xslt a.xml > a.csv
I get an incorrect output, as field 2 does not represent the attribute sequence number:
1|1|b1
1|1|b2
2|1|b1
2|1|b2
2|1|b3
Do you have any suggestions on how to get the correct output please?
Please notice that the answers provided in XSLT to order attributes do not provide a solution to this problem.
The order of attributes is irrelevant in XML. For instance, <a a1="3.0" a2="ABC"> and <a a1="3.0" a2="ABC"> are equivalent.
However this specific question is part of a larger application where it is essential to establish the order in which attributes appear in given xml files (and not in xml files that are equivalent to them).
Although, as kjhughes says in comments, attribute order is insignificant. However, you can still select them, and use the position() element to get the numbers you are after (You just can't be sure the order they are output will be the order they appear in the XML, although generally this will be the case).
Try this XSLT. Do note the nested use of xsl:for-each to select only b elements first, to get their position, before getting the attributes, which then have their own separate position.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="a/b">
<xsl:variable name="bPosition" select="position()"/>
<xsl:for-each select="#*">
<xsl:value-of select="$bPosition"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
You could use the position() of the items in the sequence of attributes that you are iterating over and combine with logic for the position of its parent element.
<xsl:template match="/">
<xsl:for-each select="a/b/#*">
<xsl:value-of select="count(../preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<!-- TODO: This is not correct -->
<xsl:value-of select="position() -
(if (count(../preceding-sibling::*)) then count(../preceding-sibling::*)+1 else 0)"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
Which produces the following output:
1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3

Setting disable-output-escaping="yes" for every xsl:text tag in the xml

say I have the following xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<display>
<xsl:for-each select="logline_t">
<xsl:text disable-output-escaping="yes"><</xsl:text> <xsl:value-of select="./line_1" <xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:text disable-output-escaping="yes"><</xsl:text> <xsl:value-of select="./line_2" <xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:text disable-output-escaping="yes"><</xsl:text> <xsl:value-of select="./line_3" <xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:for-each>
</display>
</xsl:template>
</xsl:stylesheet>
Is there a way to set disable-output-escaping="yes" to all of the xsl:text that appear in the document?
I know there is an option to put
< xsl:output method="text"/ >
and every time something like
& lt;
appears, a < will appear, but the thing is that sometimes in the values of line_1, line_2 or line_3, there is a "$lt;" that I don't want changed (this is, I only need whatever is between to be changed)
This is what I'm trying to accomplish. I have this xml:
<readlog_l>
<logline_t>
<hora>16:01:09</hora>
<texto>Call-ID: 663903<hola>396#127.0.0.1</texto>
</logline_t>
</readlog_l>
And this translation:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<display>
<screen name="<xsl:value-of select="name(.)"/>">
<xsl:for-each select="logline_t">
< field name="<xsl:for-each select="*"><xsl:value-of select="."/></xsl:for-each>" value="" type="label"/>
</xsl:for-each>
</screen>
</display>
</xsl:template>
</xsl:stylesheet>
I want this to be the output:
<?xml version="1.0"?>
<display>
<screen name="readlog_l">
<field name="16:01:09 Call-ID: 663903<hola>396#127.0.0.1 " value="" type="label">
</screen>
</display>
Note that I need the "<" inside the field name not to be escaped, this is why I can't use output method text.
Also, note that this is an example and the translations are much bigger, so this is why I'm trying to find out how not to write disable-output-escaping for every '<' or '>' I need.
Thanks!
Thanks for clarifying the question. In this case, I'm fairly sure there's no need to disable output escaping. XSLT was designed to accomplish what you're doing:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<display>
<screen name="{name(.)}">
<xsl:for-each select="logline_t">
<xsl:variable name="nameContent">
<xsl:for-each select="*">
<xsl:if test="position() > 1"><xsl:text> </xsl:text></xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
<field name="{$nameContent}" value="" type="label" />
</xsl:for-each>
</screen>
</display>
</xsl:template>
</xsl:stylesheet>
I'm a bit unclear on this point:
Note that I need the "<" inside the field name not to be escaped, this is why I can't use output method text.
Which < are you referring to? Is it the < and > around "hola"? If you left those unescaped you would wind up with invalid XML. It also looks like the name attribute in your sample output have a lot of values that aren't in the input XML. Where did those come from?
Given your expected output you don't need d-o-e at all for this. Here is a possible solution that doesn't use d-o-e, and is based on templates rather than for-each:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<display>
<screen name="{name(.)}">
<xsl:apply-templates select="logline_t"/>
</screen>
</display>
</xsl:template>
<xsl:template match="logline_t">
<field value="" type="label">
<xsl:attribute name="name">
<xsl:apply-templates select="*" mode="fieldvalue"/>
</xsl:attribute>
</field>
</xsl:template>
<xsl:template match="*[last()]" mode="fieldvalue">
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="*" mode="fieldvalue">
<xsl:value-of select="." />
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
If you want to set d-o-e on everything, that suggests you are trying to generate markup "by hand". I don't think that's a particularly good idea (in fact, I think it's a lousy idea), but if it's what you want to do, I would suggest using the text output method instead of the xml output method. That way, no escaping of special characters takes place, and therefore it doesn't need to be disabled.

How to remove empty lines in XSLT to CSV output

I have XML data which I have transformed using XSLT to output csv formatted text. My XSLT contains a <xsl:if test> clause to filter the result from the larger dataset of the input XML. This works but every line that is filtered out of the input is displayed as an empty line in the output.
I have tried <xsl:strip-space elements="*" /> and <xsl:template match="text()" /> but neither remove the empty lines.
A sample of my XML:
<?xml version="1.0" encoding="UTF-8"?>
<session_list xmlns="http://www.networkstreaming.com/namespaces/API" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<session lsid="fef672741e025ffda1acb3041f09252d">
<session_type>support</session_type>
<lseq>2899</lseq>
<start_time timestamp="1290027608">2010-11-17T16:00:08-05:00</start_time>
<end_time timestamp="1290027616">2010-11-17T16:00:16-05:00</end_time>
<duration>00:00:08</duration>
<public_site id="1">Default</public_site>
<external_key></external_key>
<session_chat_view_url>https://mysite.com/session_download.ns?lsid=l%3Dfef672741e025ffda1acb3041f09252d%3Bh%3D9bd6081f0b7fee08dcc32a58ef4cb54c7a0e233d%3Bt%3Dsd%3Bm%3Dchat&dl_action=chat&view=1&sessionType=sd</session_chat_view_url>
<session_chat_download_url>https://mysite.com/session_download.ns?lsid=l%3Dfef672741e025ffda1acb3041f09252d%3Bh%3D9bd6081f0b7fee08dcc32a58ef4cb54c7a0e233d%3Bt%3Dsd%3Bm%3Dchat&dl_action=chat&sessionType=sd</session_chat_download_url>
<file_transfer_count>0</file_transfer_count>
<primary_customer gsnumber="3">Smith, John</primary_customer>
<customer_list>
<customer gsnumber="3">
<username>Smith, John</username>
<public_ip>xxx.xxx.xxx.xxx</public_ip>
<private_ip>xxx.xxx.xxx.xxx</private_ip>
<hostname>DESKTOP</hostname>
<os>Windows 7 Enterprise x64 Edition (Build 7600)</os>
<primary_cust>1</primary_cust>
<info>
<name></name>
<company></company>
<company_code></company_code>
<issue></issue>
<details></details>
</info>
</customer>
</customer_list>
...etc...
</session>
</session_list>
My XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bg="http://www.networkstreaming.com/namespaces/API" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:text>Session ID,</xsl:text>
<xsl:text>Start Time,</xsl:text>
<xsl:text>Duration,</xsl:text>
<xsl:text>Public Site,</xsl:text>
<xsl:text>Remedy Ticket Number,</xsl:text>
<xsl:text>Customer's Name,</xsl:text>
<xsl:text>Customer's Operating System,</xsl:text>
<xsl:text>Representative's Name</xsl:text>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="bg:session_list">
<xsl:apply-templates select="bg:session"/>
</xsl:template>
<xsl:template match="bg:session">
<xsl:if test="contains(bg:customer_list/bg:customer/bg:os,'Click-To-Chat')">
<xsl:value-of select="bg:lseq"/>,<xsl:text/>
<xsl:value-of select="bg:start_time"/>,<xsl:text/>
<xsl:value-of select="bg:duration"/>,<xsl:text/>
<xsl:value-of select="bg:public_site"/>,<xsl:text/>
<xsl:value-of select="bg:external_key"/>,<xsl:text/>
<xsl:value-of select="bg:primary_customer"/>,<xsl:text/>
<xsl:value-of select="bg:customer_list/bg:customer/bg:os"/>,<xsl:text/>
<xsl:value-of select="bg:primary_rep"/>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
A sample of the output:
Session ID,Start Time,Duration,Public Site,Remedy Ticket Number,Customer's Name,Customer's Operating System,Representative's Name
6488,2011-03-14T09:17:13-04:00,00:00:06,Default,,User One,Windows® (x86) Click-To-Chat,Rep1
6489,2011-03-14T09:44:50-04:00,00:39:58,Default,,Nate,Windows® (x86) Click-To-Chat,Rep1
6494,2011-03-14T10:25:23-04:00,00:03:29,Default,,User TEST,Windows® (x86) Click-To-Chat,Rep1
6498,2011-03-14T11:01:36-04:00,,Default,,User Two,Windows® (x86) Click-To-Chat,Diane
Each of the lines between the printed lines is data that was filtered out because it didn't pass the <xsl:if test="contains(bg:customer_list/bg:customer/bg:os,'Click-To-Chat')"> but the empty lines are still printed. This output doesn't look very good when opened in excel.
Does anyone have any ideas how to remove them?
Thanks!
Have you tried putting the <xsl:text>
</xsl:text> line inside the xsl:if? This is the bit that puts a newline, so at the moment you are writing one even if you don't write the line.

xsl get array of elements

Hi
I need get array of elements (before "-" if exist) by xsl.
xml is
<Cars>
<Car Trunck="511"/>
<Car Trunck="483-20"/>
<Car Trunck="745"/>
</Cars>
xsl is
<xsl:variable name="testarr">
<xsl:for-each select="//Cars//Car/#Trunck">
<xsl:value-of select="number(substring(.,1,3))" />
</xsl:for-each>
</xsl:variable>
(i suppose that all numbers is three-digit number, if someone knows a solution for all conditions will be glad to hear the proposal)
if i do this
i get all numbers in one line: 511483745
and i need get them in array
because i also need get the max value
thanks
Hi I need get array of elements
(before "-" if exist) [...] i need get
them in array because i also need get
the max value
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="/Cars/Car/#Trunck">
<xsl:sort select="concat(substring-before(.,'-'),
substring(., 1 div not(contains(.,'-'))))"
data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of
select="concat(substring-before(.,'-'),
substring(.,1 div not(contains(.,'-'))))"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Output:
745
XPath 2.0 one line:
max(/Cars/Car/#Trunck/number(replace(.,'-.*','')))
You could use the substring-before and substring-after functions: See the excellent ZVON tutorial
http://zvon.org/xxl/XSLTreference/Output/function_substring-after.html
In your example you are only extracting the values (which are strings) which get concatenated. Perhaps you need to wrap the result in your own element
<xsl:for-each select="//Cars//Car/#Trunck">
<truck>
<xsl:value-of select="number(substring(.,1,3))" />
</truck>
</xsl:for-each>
While you have two good answers (especially that by #Alejandro), here's one from me that I think is even better:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="pTopNums" select="2"/>
<xsl:template match="/*">
<xsl:apply-templates select="*">
<xsl:sort data-type="number" order="descending"
select="substring-before(concat(#Trunck,'-'),'-')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Car">
<xsl:if test="not(position() > $pTopNums)">
<xsl:value-of select=
"substring-before(concat(#Trunck,'-'),'-')"/>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document (the originally provided one, slightly changed to be more challenging):
<Cars>
<Car Trunck="483-20"/>
<Car Trunck="311"/>
<Car Trunck="745"/>
</Cars>
produces the wanted, correct result (the top two numbers that are derived from #Trunck as specified in the question):
745
483

Compare date-periods using XSLT

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!
Here is an example to do it directly in xslt 2.0 and should work with most date delimeters:
<?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 < $dateToCheck and $dateToCheck < $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 < current-date() and current-date() < $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>
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">
<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 <= StartDate) and
(Child/EndDate >= 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.
What's wrong with number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)?
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.