[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

Subject: Re: Creating new, distinct groups of ranges from an aggregation of individual ranges
From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 19 Nov 2014 10:27:48 -0000
Re:  Creating new
Hi Heiko & Michael,

On 19.11.2014 02:20, Heiko Niemann kontakt@xxxxxxxxxxxxxxxx wrote:
Hi Gerrit,

since my first name is not very international I listen to a whole range of
names: from Heeeko to Hayoko. :)

Talking about ranges. I had the same question about 219, Michael clarified
and since your code covers it already I would suggest Michael to follow
your approach. They are similar anyhow.

I noticed two things though:

1) parsing the ranges does not cover missing leading zeros (if you e.g.
add 8880889 to a aircraft-range it won't show in the result, 08880889
will); first I also looked at using analyze-string but dropped it so I use
following code now (adjusted to the elements you use):

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:

<pass3>
     <range start="200" end="200"/>
     <range start="200" end="200"/>
     <range start="201" end="204"/>


and if you add 0201 instead the result is:


<pass3>
       <range start="201" end="200"/>
       <range start="201" end="201"/>
       <range start="202" end="204"/>

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[. &lt; 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 &gt; current()/@end + 1]
[following-sibling::range/@start &lt; 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>

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.