This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: substring manipulation to wrap text in an SVG <rect>


Firstly, the following template returns the length of the first line of text
to output. There are other ways to write it but I've chosen to be simple and
verbose.

<xsl:template name="line-length">
  <xsl:param name="text"/>
  <xsl:choose>
  <xsl:when test="string-length($text) &lt; 18">
    <xsl:value-of select="string-length($text)"/>
  </xsl:when>
  <xsl:when test="substring($text, 18, 1) = ' '">18</xsl:when>
  <xsl:when test="substring($text, 17, 1) = ' '">17</xsl:when>
  <xsl:when test="substring($text, 16, 1) = ' '">16</xsl:when>
  ...
  <xsl:otherwise>1</xsl:otherwise>
  </xsl:choose>
</xsl:template>

Now you need a recursive template to process your chunk of text. The
template outputs a <text> element for the first line, and calls itself to
output <text> elements for the remaining lines:

<xsl:template name="output-text">
  <xsl:param name="text"/>
  <xsl:variable name="first-len">
    <xsl:call-template name="line-length">
      <xsl:with-param name="$text"/>
    </xsl:call-template>
  </xsl:variable>
  <text><xsl:value-of select="substring($text, 1, $first-len)"/></text>
  <xsl:variable name="rest" select="substring($text, $first-len+1)"/>
  <xsl:if test="$rest">
    <xsl:call-template name="output-text">
      <xsl:with-param name="text" select="$rest"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

I haven't included the code to output the attributes of the <text> element,
this may need extra parameters to the template.

Some comments on your code:

Match patterns never need to start with "//". It's best not to include a
leading "//" because it means that the rules for assigning a default
priority don't work as intended.

Using disable-output-escaping="yes" when your output is intended to be
well-formed XML is a clear indication that you haven't yet mastered XSLT! It
is never necessary in such circumstances, and is always undesirable, because
it means your stylesheet can only produce serialized XML, not a tree that
can be input to another process.

Using <xsl:element> and <xsl:attribute> with fixed element and attribute
names is much harder to write and harder to read than using literal result
elements and attribute value templates.

Using <xsl:variable> with content consisting of a single <xsl:value-of>
instruction can in nearly all cases be replaced by an <xsl:variable> with a
select attribute, which again is easier to read and easier to write.

ancestor::*[self::HOTSPOT] is a rather longwinded way of writing
ancestor::HOTSPOT.

Mike Kay

>
> I am trying to wrap text inside of an svg <rect> element thru svg. Im
> getting close, just need to get over this last hurdle.
> Right now, I take the width of the rectangle, multiply it by
> 18, and round
> this number, to give me the number of characters
> that will fit across the rectangle in 1 line.
> I then use substring() to take the calculated number of
> characters and draw
> them, then take the next set of characters and so on.
>
> This part works, though the xsl is not pretty.
>
> Now, I need it to be a little more intelligent. I want to stop it from
> cutting off words in the middle of them..for example, instead of
>
> This is some te
> xt. See how it c
> uts off.
>
> This is some
> text. Now it
> doesnt cut off
>
>
> I havent thought of a way to do this yet with only having
> substring()
> substring-before()
> substring-after()
> contains()
> starts-with()
>
> at my disposal. If there were some sort of indexOf('some character or
> string') kind of function, that would return the position within the
> string of the argument given to it..well that would make this easier.
>
> So....any ideas? Ive included sample xsl and xml below
>
> thanks,
>
> Paul
>
> xsl:
>
>
> <xsl:template match="//HOTSPOT">
> <xsl:variable name="xval">
> <xsl:value-of select="number(substring-before(@X, 'i'))"/>
> </xsl:variable>
> <xsl:variable name="yval">
> <xsl:value-of select="number(substring-before(@Y, 'i'))"/>
> </xsl:variable>
> <xsl:variable name="wval">
> <xsl:value-of select="number(substring-before(@W, 'i')) div 15"/>
> </xsl:variable>
> <xsl:variable name="hval">
> <xsl:value-of select="number(substring-before(@H, 'i')) div 9"/>
> </xsl:variable>
> <xsl:element name="g">
>
> <!--draw the rectangle-->
> <xsl:element name="rect">
> <xsl:attribute name="id"><xsl:value-of
> select="@ID"/></xsl:attribute>
> <xsl:attribute name="x"><xsl:value-of select="@X"/></xsl:attribute>
> <xsl:attribute name="y"><xsl:value-of select="@Y"/></xsl:attribute>
> <xsl:attribute name="width"><xsl:value-of
> select="@W"/></xsl:attribute>
> <xsl:attribute name="height"><xsl:value-of
> select="@H"/></xsl:attribute>
> <xsl:attribute name="style"><xsl:text>fill:white; fill-opacity:0;
> stroke:red; stroke-width:1; stroke-linejoin:bevel;
> stroke-dasharray:5,2</xsl:text></xsl:attribute>
> </xsl:element>
> <--set up the containing text element-->
> <xsl:element name="text">
> <xsl:attribute name="x"><xsl:value-of select="$xval + $wval"
> /><xsl:text>in</xsl:text></xsl:attribute>
> <xsl:attribute name="y"><xsl:value-of select="$yval + $hval"
> /><xsl:text>in</xsl:text></xsl:attribute>
> <xsl:attribute
> name="style"><xsl:text>font-family:'Arial';font-size:10;fill-r
> ule:nonzero;cl
> ip-rule:nonzero;</xsl:text></xsl:attribute>
> <xsl:apply-templates/>
> </xsl:element>
> </xsl:element>
> <xsl:text disable-output-escaping="yes">
> &lt;/a&gt;
> </xsl:text>
> </xsl:template>
>
> <!--this number goes on the first line-->
> <xsl:template match="//FIGURE[descendant::GRAPHIC[substring(@FILE,
> string-length(@FILE)-2)= 'svg']]//CALLOUT-NUMBER">
> <xsl:element name="tspan">
> <xsl:attribute name="style">
> <xsl:text>font-size:12;font-weight:bold</xsl:text>
> </xsl:attribute>
> <xsl:value-of select="."/>
> </xsl:element>
>
> <!-- now this text needs to wrap inside the rectangle-->
> <xsl:template match="//P">
> <xsl:variable name="charsperline">
> <xsl:value-of
> select="round(number(substring-before(ancestor::*[self::HOTSPO
> T][1]/@W,
> 'i')) * 18.732)"/>
> </xsl:variable>
> <xsl:variable name="xval">
> <xsl:value-of
> select="number(substring-before(ancestor::*[self::HOTSPOT][1]/
> @X, 'i'))"/>
> </xsl:variable>
> <xsl:variable name="wval">
> <xsl:value-of
> select="number(substring-before(ancestor::*[self::HOTSPOT][1]/
> @W, 'i')) div
> 15"/>
> </xsl:variable>
>
> <xsl:element name="tspan">
> <xsl:attribute name="x"><xsl:value-of select="$xval + $wval"
> /><xsl:text>in</xsl:text></xsl:attribute>
> <xsl:attribute name="dy"><xsl:text>1em</xsl:text></xsl:attribute>
> <!--Here get the first line of characters-->
> <xsl:value-of select="substring(., 0, $charsperline)"/>
> </xsl:element>
> <xsl:element name="tspan">
> <xsl:attribute name="x"><xsl:value-of select="$xval + $wval"
> /><xsl:text>in</xsl:text></xsl:attribute>
> <xsl:attribute name="dy"><xsl:text>1em</xsl:text></xsl:attribute>
> <!--now get the next line of characters-->
> <xsl:value-of select="substring(., $charsperline, $charsperline)"/>
> </xsl:element>
> <xsl:element name="tspan">
> <xsl:attribute name="x"><xsl:value-of select="$xval + $wval"
> /><xsl:text>in</xsl:text></xsl:attribute>
> <xsl:attribute name="dy"><xsl:text>1em</xsl:text></xsl:attribute>
> <!--now get the last line of characters-->
> <xsl:value-of select="substring(., $charsperline*2, $charsperline)"/>
> </xsl:element>
> </xsl:template>
>
>
> sample xml input...........
>
>  <FIGURE POSITION="SPAN" DISPLAY-TYPE="POPUP"
> DISPLAY-HOTSPOTS="DISPLAY"
> ID="svc.bt08_pe.0000110477">
>                         <GRAPHIC FILE="whatever.svg" WIDTH="9.295in"
> HEIGHT="6.521in" />
>                         <HOTSPOTS SIZEX="9.253in" SIZEY="6.500in">
>                            <LINE X1="1.421" Y1="1.192"
> X2="2.807" Y2="1.017"
> WIDTH="0.007"/>
>                            <HOTSPOT X="1.258in" Y="1.162in"
> W="0.951in"
> H="0.462in" ID="svc.bt08_pe.0000110478">
>                               <CALLOUT-NUMBER>2</CALLOUT-NUMBER>
>                               <P>Text Text Text Text Text
> Text Text</P>
>                            </HOTSPOT>
>                            <HOTSPOT X="7.553in" Y="1.603in"
> W="1.165in"
> H="0.599in" ID="svc.bt08_pe.0000110481">
>                               <CALLOUT-NUMBER>1</CALLOUT-NUMBER>
>                               <P>This is a bunch of text, a
> whole lot. Ther
> text just keeps coming.</P>
>                            </HOTSPOT>
>                            <LINE X1="7.480" Y1="1.636"
> X2="5.953" Y2="1.565"
> WIDTH="0.007"/>
>                            <HOTSPOT X="0.109in" Y="2.290in"
> W="1.197in"
> H="0.510in">
>                               <CALLOUT-NUMBER>3</CALLOUT-NUMBER>
>                               <P>Words words words words words words
> words</P>
>                            </HOTSPOT>
>                            <LINE X1="0.244" Y1="2.324"
> X2="1.648" Y2="2.152"
> WIDTH="0.007"/>
>                         </HOTSPOTS>
>                         <CAPTION>Lots more text is here. Check it
> out.</CAPTION>
>                      </FIGURE>
>
>
>
> __________________________________________________________
>
>  <<...OLE_Obj...>>
> Paul Wilcox
> Software Engineer
> Global Knowledge and Language Services
> XEROX
> Phone #: 8*222-4727/(716) 422-4727
> Email: Paul.Wilcox@usa.xerox.com
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]