[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Creating new, distinct groups of ranges from an a
Hi Heiko & Michael,
On 19.11.2014 02:20, Heiko Niemann kontakt@xxxxxxxxxxxxxxxx wrote: Hi Gerrit, I emitted an xsl:message that would report any input token that doesnbt match '^\d{4}(\d{4})?$'. It might be a better idea to add terminate="yes" to that message instead of heuristically fixing the data, but Ibm not the one to make a call on this. 2) If you add e.g. 0200 to a list the result will show: Youbre right, therebs still a bug. The matching pattern in the template with xml:id="A" should be changed from match="range[1][not(@start = following-sibling::*[1]/@start)]" to match="range[1][not(@start = following-sibling::*[1]/(@start|@end))]" Letbs see which other bugs are left uncovered by our anecdotal test cases. Ibm waiting for the FAA to knock on my door in order to investigate a future fatal incident caused by flaky XSLT codeb& Ibm posting the complete revised code below. There are no templates in #default mode any more which should help in integrating the code. Ibve added a debug parameter. Apply aircrafts.xsl with debug=yes to get the intermediate stepsb results in /ranges/debug in the output. Gerrit ---------------------- ranges.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output indent="yes"/> <xsl:param name="debug" select="'yes'"/> <xsl:template match="ranges" mode="ranges"> <xsl:variable name="pass1" as="element(pass1)"> <pass1> <!-- eliminates duplicate start/end attributes and creates a new range for each distinct start and end value: --> <xsl:for-each-group select="range/(@start|@end)" group-by="string-join((name(), .), '=')"> <xsl:sort select="." data-type="number"/> <range> <xsl:sequence select="."/> <!-- adds a start attribute to the end attribute iff the start attribute's value is smaller than the end attribute's: --> <xsl:sequence select="../@start[. < current()]"/> </range> </xsl:for-each-group> </pass1> </xsl:variable> <xsl:variable name="pass2" as="element(pass2)"> <pass2> <!-- Fill gaps with new ranges (Heikobs test case) --> <xsl:apply-templates select="$pass1/range" mode="ranges_pass2"/> </pass2> </xsl:variable> <xsl:variable name="pass3" as="element(pass3)"> <pass3> <!-- Replaces the existing start attribute with the nearest value available, looking behind (template with xml:id="B" below). Ranges without an end attribute will be eliminated by virtue of the built-in template. Except for the first range (template with xml:id="A" below): If it doesn't have an end attribute, and if its start attribute is not equal to the next range's start attribute, the next suitable end attribute will be added. --> <xsl:apply-templates select="$pass2/range" mode="ranges_pass3"/> </pass3> </xsl:variable> <ranges> <xsl:if test="$debug = 'yes'"> <debug> <xsl:sequence select="."/> <xsl:sequence select="$pass1"/> <xsl:sequence select="$pass2"/> </debug> </xsl:if> <xsl:sequence select="$pass3/*"/> </ranges> </xsl:template> <xsl:template match="range" mode="ranges_pass2"> <xsl:copy-of select="."/> </xsl:template> <xsl:template mode="ranges_pass2" match="range[@end] [following-sibling::range[1]/@start > current()/@end + 1] [following-sibling::range/@start < current()/@end]"> <xsl:copy-of select="."/> <range start="{@end + 1}" end="{following-sibling::range[1]/@start - 1}" inserted-in="pass2"/> </xsl:template> <xsl:template mode="ranges_pass3" xml:id="A" match="range[1][not(@start = following-sibling::*[1]/(@start|@end))]"> <xsl:copy> <xsl:copy-of select="@start"/> <xsl:attribute name="end" select="following-sibling::range[@start][1]/@start - 1"/> </xsl:copy> </xsl:template> <xsl:template match="range[@end]" mode="ranges_pass3" xml:id="B"> <xsl:copy> <xsl:attribute name="start" select="max((@start, preceding-sibling::*[@start][1]/@start, preceding-sibling::*[@end][1]/@end + 1))"/> <xsl:copy-of select="@end"/> </xsl:copy> </xsl:template> </xsl:stylesheet> ---------------------- aircrafts.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:import href="ranges.xsl"/> <xsl:param name="debug" select="'no'"/> <xsl:template match="group[aircraft-range]"> <xsl:variable name="parse" as="element(ranges)"> <ranges> <xsl:apply-templates mode="parse"/> </ranges> </xsl:variable> <xsl:apply-templates select="$parse" mode="ranges"/> </xsl:template> <xsl:template match="aircraft-range" mode="parse"> <xsl:for-each select="tokenize(., '\s+')"> <xsl:analyze-string select="." regex="^(\d{{4}})(\d{{4}})?$"> <xsl:matching-substring> <range start="{number(regex-group(1))}" end="{number((regex-group(2)[normalize-space()], regex-group(1))[1])}"/> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:message select="'Could not parse ', ."/> </xsl:non-matching-substring> </xsl:analyze-string> </xsl:for-each> </xsl:template> </xsl:stylesheet>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|