Re: [xsl] How to declaratively describe a mapping that involves breaking a string apart and reassembling the parts with an additional symbol?

Subject: Re: [xsl] How to declaratively describe a mapping that involves breaking a string apart and reassembling the parts with an additional symbol?
From: "Piez, Wendell A. (Fed) wendell.piez@xxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 13 Mar 2024 19:41:23 -0000
Hi again Roger,

So here is an XSpec I wrote as a starter illustration for you:

<x:description xmlns:x="";

   <x:variable name="cardinal-points"

   <x:scenario label="Roger's mapping example">
      <x:scenario label="A magnetic variation">
         <x:expect label="maps into a more explicit form">
         <x:expect label="has its direction marked by expanding its initial
         <x:expect label="has its value marked by expanding the rest of the
         <x:expect label="has its direction marked with a known value"
            test="/*/magneticVariationEWT = $cardinal-points"/>
         <x:expect label="has its value marked as a number"
            test="/*/magneticVariationValue castable as xs:double"/>
         <x:expect label="has a value matching regex '\d\d\d\.\d' - four
digits, one decimal place"
            test="/*/magneticVariationValue => matches('\d\d\d\.\d')"/>


I also have XSLT that passes these tests on inputs like yours.

Note that presently certain assumptions are made that are almost certainly
wrong. For example I decided to enable any of the four cardinal points
'North', 'East', 'West' and 'South'. (Whereas your description suggests only E
and W should be recognized.) And even where the testing is not wrong, it could
be extended to be more complete especially around edge cases.

It is, however, enough to suggest how a set of tests can fill the
'specification gap' you are noticing between requirements and code. By
reflecting the way the results should look, the testing can assure both their
quality (however you define that) and their relation to the source data.
Naturally, it is possible and even likely that tests will overlap, etc. (as
shown here) -- they aim for correctness, legibility and completeness, not

Importantly, these tests can also be run in an XSpec engine to determine if
your XSLT performs the mapping correctly.

And of those 'expect' statements, only the first is tied to the input here;
the others are more general and could presumably be reused on any case you
want to test.

Here is my XSLT (for checking the assumptions):

<xsl:variable name="directions" as="element()*">

<xsl:template match="Magnetic_Variation" expand-text="true">
   <xsl:variable name="initial-letter" select="substring(.,1,1)"/>
   <xsl:variable name="numeric-value"
select="substring-after(.,$initial-letter)[. castable as xs:integer] =>
      <magneticVariationEWT>{ $directions[starts-with(.,$initial-letter)]
      <magneticVariationValue>{ format-number($numeric-value div 10, '000.0')

If it were real, one thing I would consider extending here would be testing to
expose the behaviors around badly-formed inputs. Unless I could also conduct
testing upstream for example with Schematron on the source data, and maybe
even then.

As my tai chi teacher says -- enjoy! -- Wendell

-----Original Message-----
From: Roger L Costello costello@xxxxxxxxx
Sent: Tuesday, March 12, 2024 9:21 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] How to declaratively describe a mapping that involves breaking
a string apart and reassembling the parts with an additional symbol?

Hi Folks,

I am mapping an old XML format to a new XML format.

To carry out the mapping, I want to write as little code as possible; instead,
I want to declaratively describe the mapping in an XML document and then have
a tiny piece of generic code which, with little or no knowledge of the old and
new formats, carries out the mappings described in the XML document.

I am having a hard time with some descriptions. Here's an illustration:

I want to map this old XML:


to this new XML:


Here is one way to perform the mapping:

        <xsl:value-of select="
            if (substring($magVar,1,1) eq 'E') then 'East'
            else if (substring($magVar,1,1) eq 'W') then 'West'
            else 'True'"/>
        <xsl:value-of select="

That is a fine way to perform the mapping. However, it is not the way that I
want to do it because the mapping is expressed procedurally, not
declaratively. I want the mapping expressed declaratively.

I can declaratively express part of the mapping -- map the first character E
to East, W to West, T to True -- using this description:

            <Magnetic_Variation col="1" length="1">E</Magnetic_Variation>
            <Magnetic_Variation col="1" length="1">W</Magnetic_Variation>
            <Magnetic_Variation col="1" length="1">T</Magnetic_Variation>

I do not know how to declaratively describe the other part of the mapping --
map dddd to ddd.d (where d = digit). I could do this:

            <Magnetic_Variation col="2" length="4"></Magnetic_Variation>

But that is unacceptable (to me) because the description contains code.

How do I declaratively describe this mapping?

Bonus points if you can also answer this question:

Computer Science Theory Question: If it is impossible to declaratively express
the above mapping, does that mean there is a limit to declarative
descriptions? Is the set of declarative descriptions smaller than the set of
procedural descriptions?


Current Thread