Lengths in XSL-FO - How to add them

1. Adding xsl-fo lengths? E.g. 10mm + 6cm

1.

Adding xsl-fo lengths? E.g. 10mm + 6cm

David Carlisle





I asked, 
>  Now there's a feature that would help out XSL-FO!
>  Arithmetic that catered for 100mm+25mm and added them with a common unit!

And David Carlisle replied with this! I'm impressed.

With this input

<x>
<a>
  <c width='10m'/>
  <c width='3mm'/>
  <c width='4mm'/>
  <c width='6cm'/>
</a>
<a>
  <c width='2mm'/>
  <c width='3mm'/>
  <c width='4.3mm'/>
  <c width='3in'/>
  <c width='3pt'/>
</a>
</x>

And this stylesheet

<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="data:,x"
 version="2.0">

<xsl:template match="a">
 [<xsl:value-of select="x:sum-widths(c/@width)"/>]
</xsl:template>

<xsl:function name="x:sum-widths">
 <xsl:param name="x"/>
<xsl:value-of select="
 format-number(sum(for $i in $x
 return
  if (ends-with($i,'mm')) then number(substring-before($i,'mm')) else
  if (ends-with($i,'cm')) then 10*number(substring-before($i,'cm')) else
  if (ends-with($i,'m')) then 100*number(substring-before($i,'m')) else
  if (ends-with($i,'in')) then 25.4*number(substring-before($i,'in')) else
  if (ends-with($i,'ft')) then  304.8*number(substring-before($i,'ft')) else
  if (ends-with($i,'pt')) then 25.4*number(substring-before($i,'pt')) div 72
else
      $i),'#.0#mm')
 "/> 
</xsl:function>

</xsl:stylesheet>
$ saxon7 lengths.xml lengths.xsl
<?xml version="1.0" encoding="UTF-8"?>

produces this output

 [1067.0mm]


 [86.56mm]