Subject: RE: [xsl] substring manipulation to wrap text in an SVG <rect> From: "Michael Kay" <mhkay@xxxxxxxxxxxx> Date: Sun, 16 Sep 2001 23:20:21 +0100 |
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) < 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"> > </a> > </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@xxxxxxxxxxxxx > > > XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list > XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] substring manipulation to wra, Wilcox, Paul | Thread | [xsl] substring manipulation to wra, Mark Nahabedian |
RE: [xsl] How do you get the non-tr, Julian Reschke | Date | [xsl] Non-existing node, Casadome, Francisco |
Month |