Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > File formating with XSLT

Reply
Thread Tools

File formating with XSLT

 
 
olivier.scalbert@algosyn.com
Guest
Posts: n/a
 
      01-31-2007
Hello,

>From the source file, I need to create with XSLT a result file with

the following constraints:

source:
<Source>
<Item>AAA</Item>
<Item>BBBBBBBBBBB</Item>
<Item>CCCCCCCCC</Item>
<Item>DDDDDDDDDDDDDDD</Item>
<Item>EEEEE</Item>
<Item>FF</Item>
<Item>G</Item>
</Source>

result: (text file with line length = 16, with spaces)
AAA BBBBBBBBBBB
CCCCCCCCC
DDDDDDDDDDDDDDD
EEEEE FF G

Each line of the output file is composed of Item texts separated by
one space.
If by adding a new item text on the line we have more than 16
characters then pad the current line with spaces and copy the item
text to a new line.

I do not know if it is possible to do that in XSLT.
Thanks for your help.

Olivier

 
Reply With Quote
 
 
 
 
Andy Dingley
Guest
Posts: n/a
 
      01-31-2007
On 31 Jan, 14:02, "olivier.scalb...@algosyn.com"
<olivier.scalb...@algosyn.com> wrote:
> I do not know if it is possible to do that in XSLT.


Dead easy, just add <xslutput method="text" /> to the top of your
stylesheet.
http://www.w3.org/TR/xslt#section-Text-Output-Method

 
Reply With Quote
 
 
 
 
Dimitre Novatchev
Guest
Posts: n/a
 
      01-31-2007
Use the FXSL stylesheet file:

strSplit-to-Lines.xsl

And modify it appropriately for your case.

This transformation (just modified the above stylesheet, calling the
template with lineLength=16):

<xsl:stylesheet version="2.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:str-split2lines-func="f:str-split2lines-func"
exclude-result-prefixes="f str-split2lines-func"
>


<xsl:import href="str-foldl.xsl"/>

<!-- to be applied on text.xml -->

<str-split2lines-func:str-split2lines-func/>

<xslutput indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="/">
<xsl:call-template name="str-split-to-lines">
<xsl:with-param name="pStr"
select="concat(normalize-space(/), ' ')"/>
<xsl:with-param name="pLineLength" select="16"/>
<xsl:with-param name="pDelimiters" select="' '"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="str-split-to-lines">
<xslaram name="pStr"/>
<xslaram name="pLineLength" select="60"/>
<xslaram name="pDelimiters" select="' '"/>

<xsl:variable name="vsplit2linesFun"
select="document('')/*/str-split2lines-func:*[1]"/>

<xsl:variable name="vrtfParams">
<delimiters><xsl:value-of select="$pDelimiters"/></delimiters>
<lineLength><xsl:copy-of select="$pLineLength"/></lineLength>
</xsl:variable>

<xsl:variable name="vResult">
<xsl:call-template name="str-foldl">
<xsl:with-param name="pFunc" select="$vsplit2linesFun"/>
<xsl:with-param name="pStr" select="$pStr"/>
<xsl:with-param name="pA0" select="$vrtfParams"/>
</xsl:call-template>
</xsl:variable>

<xsl:for-each select="$vResult/line">
<xsl:for-each select="word">
<xsl:value-of select="concat(., ' ')"/>
</xsl:for-each>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>

<xsl:template match="str-split2lines-func:*" mode="f:FXSL">
<xslaram name="arg1" select="/.."/>
<xslaram name="arg2"/>

<xsl:copy-of select="$arg1/*[position() &lt; 3]"/>
<xsl:copy-of select="$arg1/line[position() != last()]"/>

<xsl:choose>
<xsl:when test="contains($arg1/*[1], $arg2)">
<xsl:if test="string($arg1/word)">
<xsl:call-template name="fillLine">
<xsl:with-param name="pLine" select="$arg1/line[last()]"/>
<xsl:with-param name="pWord" select="$arg1/word"/>
<xsl:with-param name="pLineLength" select="$arg1/*[2]"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsltherwise>
<xsl:copy-of select="$arg1/line[last()]"/>
<word><xsl:value-of select="concat($arg1/word, $arg2)"/></word>
</xsltherwise>
</xsl:choose>
</xsl:template>

<!-- Test if the new word fits into the last line -->
<xsl:template name="fillLine">
<xslaram name="pLine" select="/.."/>
<xslaram name="pWord" select="/.."/>
<xslaram name="pLineLength" />

<xsl:variable name="vnWordsInLine" select="count($pLine/word)"/>
<xsl:variable name="vLineLength" select="string-length($pLine) +
$vnWordsInLine"/>
<xsl:choose>
<xsl:when test="not($vLineLength + string-length($pWord) >
$pLineLength)">
<line>
<xsl:copy-of select="$pLine/*"/>
<xsl:copy-of select="$pWord"/>
</line>
</xsl:when>
<xsltherwise>
<xsl:copy-of select="$pLine"/>
<line>
<xsl:copy-of select="$pWord"/>
</line>
<word/>
</xsltherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

Produces the wanted results (the lines are truncated but padding each line
to 16 chars width is left as an exercise to the reader ) )

AAA BBBBBBBBBBB
CCCCCCCCC
DDDDDDDDDDDDDDD
EEEEE FF G

Cheers,
Dimitre Novatchev.


<> wrote in message
news: oups.com...
> Hello,
>
>>From the source file, I need to create with XSLT a result file with

> the following constraints:
>
> source:
> <Source>
> <Item>AAA</Item>
> <Item>BBBBBBBBBBB</Item>
> <Item>CCCCCCCCC</Item>
> <Item>DDDDDDDDDDDDDDD</Item>
> <Item>EEEEE</Item>
> <Item>FF</Item>
> <Item>G</Item>
> </Source>
>
> result: (text file with line length = 16, with spaces)
> AAA BBBBBBBBBBB
> CCCCCCCCC
> DDDDDDDDDDDDDDD
> EEEEE FF G
>
> Each line of the output file is composed of Item texts separated by
> one space.
> If by adding a new item text on the line we have more than 16
> characters then pad the current line with spaces and copy the item
> text to a new line.
>
> I do not know if it is possible to do that in XSLT.
> Thanks for your help.
>
> Olivier
>



 
Reply With Quote
 
olivier.scalbert@algosyn.com
Guest
Posts: n/a
 
      01-31-2007
> Dead easy, just add <xslutput method="text" /> to the top of your
> stylesheet.http://www.w3.org/TR/xslt#section-Text-Output-Method


Thanks, but I do not understand your answer. How to limit the line
length to 16 chars ? How to group small item texts in one line ? How
to separate item text with space ?

 
Reply With Quote
 
p.lepin@ctncorp.com
Guest
Posts: n/a
 
      01-31-2007
On Jan 31, 4:02 pm, "olivier.scalb...@algosyn.com"
<olivier.scalb...@algosyn.com> wrote:
> <Source>
> <Item>AAA</Item>
> <Item>BBBBBBBBBBB</Item>
> <Item>CCCCCCCCC</Item>
> <Item>DDDDDDDDDDDDDDD</Item>
> <Item>EEEEE</Item>
> <Item>FF</Item>
> <Item>G</Item>
> </Source>
>
> result: (text file with line length = 16, with spaces)
> AAA BBBBBBBBBBB
> CCCCCCCCC
> DDDDDDDDDDDDDDD
> EEEEE FF G
>
> Each line of the output file is composed of Item texts
> separated by one space.
> If by adding a new item text on the line we have more
> than 16 characters then pad the current line with spaces
> and copy the item text to a new line.
>
> I do not know if it is possible to do that in XSLT.


It certainly is possible, but fairly... perverse. XSLT is
not very good at stuff like that.

Just for the heck of it:

<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput method="text"/>
<xslaram name="max-length" select="16"/>
<xslaram name="pad-with" select="'.'"/>
<xsl:template match="Source">
<xsl:apply-templates select="Item[1]"/>
</xsl:template>
<xsl:template match="Item">
<xslaram name="cur-position" select="0"/>
<xsl:variable name="cur-length"
select="string-length(.)"/>
<xsl:variable name="new-position">
<xsl:choose>
<xsl:when test="0 = $cur-position">
<xsl:value-of
select="$cur-position + $cur-length"/>
</xsl:when>
<xsltherwise>
<xsl:value-of
select="$cur-position + $cur-length + 1"/>
</xsltherwise>
</xsl:choose>
</xsl:variable>
<xsl:if
test=
"
($max-length &lt; $cur-length) or
(0 = $cur-length)
">
<xsl:message
terminate="yes">Invalid entity.</xsl:message>
</xsl:if>
<xsl:choose>
<xsl:when test="$new-position &gt; $max-length">
<xsl:call-template name="pad-space">
<xsl:with-param name="position"
select="$cur-position"/>
</xsl:call-template>
<xsl:text>
</xsl:text>
<xsl:value-of select="."/>
<xsl:apply-templates
select="following-sibling::Item[1]">
<xsl:with-param name="cur-position"
select="$cur-length"/>
</xsl:apply-templates>
<xsl:if test="not(following-sibling::Item[1])">
<xsl:call-template name="pad-space">
<xsl:with-param name="position"
select="$cur-position"/>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:when>
<xsltherwise>
<xsl:if test="0 &lt; $cur-position">
<xsl:value-of select="$pad-with"/>
</xsl:if>
<xsl:value-of select="."/>
<xsl:apply-templates
select="following-sibling::Item[1]">
<xsl:with-param name="cur-position"
select="$new-position"/>
</xsl:apply-templates>
<xsl:if test="not(following-sibling::Item[1])">
<xsl:call-template name="pad-space">
<xsl:with-param name="position"
select="$new-position"/>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:if>
</xsltherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="pad-space">
<xslaram name="position"/>
<xsl:variable name="left"
select="$max-length - $position"/>
<xsl:if test="0 &lt; $left">
<xsl:value-of select="$pad-with"/>
<xsl:call-template name="pad-space">
<xsl:with-param name="position"
select="$position + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

Not tested on anything but the sample document provided by
the OP. Note that on large documents it is likely to barf
all over the stack and die horrible death. So I would
strongly advise against deploying it in production
environments without some serious tinkering beforehand
(preferrably the tinkering would involve rewriting the
transformation in a language more suitable for the task).

--
Pavel Lepin

 
Reply With Quote
 
olivier.scalbert@algosyn.com
Guest
Posts: n/a
 
      01-31-2007
Thank you very much for your help.
As the input source file is also generated by an XSLT transformation,
do you think I can hook your function inside this transformation, and
avoid the intermediary file ?

Olivier

 
Reply With Quote
 
olivier.scalbert@algosyn.com
Guest
Posts: n/a
 
      01-31-2007
Thanks Pavel!

 
Reply With Quote
 
Dimitre Novatchev
Guest
Posts: n/a
 
      02-01-2007

<> wrote in message
news: oups.com...
> Thank you very much for your help.
> As the input source file is also generated by an XSLT transformation,
> do you think I can hook your function inside this transformation, and
> avoid the intermediary file ?
>
> Olivier
>


Yes, this is a standard practice.

In XSLT 1.0 use the xxx:node-set() extension to convert the RTF results of
the first transformation to a regular tree.

In XSLT 2.0 this is not necessary.


Cheers,
Dimitre Novatchev


 
Reply With Quote
 
Dimitre Novatchev
Guest
Posts: n/a
 
      02-01-2007
> Note that on large documents it is likely to barf
> all over the stack and die horrible death. So I would
> strongly advise against deploying it in production



Not necessarily. One can use a DVC (Divide and Conquer) approach, which
requires as little as Log2(N) maximum stack depth.


Cheers,
Dimitre Novatchev

<> wrote in message
news: oups.com...
> On Jan 31, 4:02 pm, "olivier.scalb...@algosyn.com"
> <olivier.scalb...@algosyn.com> wrote:
>> <Source>
>> <Item>AAA</Item>
>> <Item>BBBBBBBBBBB</Item>
>> <Item>CCCCCCCCC</Item>
>> <Item>DDDDDDDDDDDDDDD</Item>
>> <Item>EEEEE</Item>
>> <Item>FF</Item>
>> <Item>G</Item>
>> </Source>
>>
>> result: (text file with line length = 16, with spaces)
>> AAA BBBBBBBBBBB
>> CCCCCCCCC
>> DDDDDDDDDDDDDDD
>> EEEEE FF G
>>
>> Each line of the output file is composed of Item texts
>> separated by one space.
>> If by adding a new item text on the line we have more
>> than 16 characters then pad the current line with spaces
>> and copy the item text to a new line.
>>
>> I do not know if it is possible to do that in XSLT.

>
> It certainly is possible, but fairly... perverse. XSLT is
> not very good at stuff like that.
>
> Just for the heck of it:
>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xslutput method="text"/>
> <xslaram name="max-length" select="16"/>
> <xslaram name="pad-with" select="'.'"/>
> <xsl:template match="Source">
> <xsl:apply-templates select="Item[1]"/>
> </xsl:template>
> <xsl:template match="Item">
> <xslaram name="cur-position" select="0"/>
> <xsl:variable name="cur-length"
> select="string-length(.)"/>
> <xsl:variable name="new-position">
> <xsl:choose>
> <xsl:when test="0 = $cur-position">
> <xsl:value-of
> select="$cur-position + $cur-length"/>
> </xsl:when>
> <xsltherwise>
> <xsl:value-of
> select="$cur-position + $cur-length + 1"/>
> </xsltherwise>
> </xsl:choose>
> </xsl:variable>
> <xsl:if
> test=
> "
> ($max-length &lt; $cur-length) or
> (0 = $cur-length)
> ">
> <xsl:message
> terminate="yes">Invalid entity.</xsl:message>
> </xsl:if>
> <xsl:choose>
> <xsl:when test="$new-position &gt; $max-length">
> <xsl:call-template name="pad-space">
> <xsl:with-param name="position"
> select="$cur-position"/>
> </xsl:call-template>
> <xsl:text>
> </xsl:text>
> <xsl:value-of select="."/>
> <xsl:apply-templates
> select="following-sibling::Item[1]">
> <xsl:with-param name="cur-position"
> select="$cur-length"/>
> </xsl:apply-templates>
> <xsl:if test="not(following-sibling::Item[1])">
> <xsl:call-template name="pad-space">
> <xsl:with-param name="position"
> select="$cur-position"/>
> </xsl:call-template>
> <xsl:text>
> </xsl:text>
> </xsl:if>
> </xsl:when>
> <xsltherwise>
> <xsl:if test="0 &lt; $cur-position">
> <xsl:value-of select="$pad-with"/>
> </xsl:if>
> <xsl:value-of select="."/>
> <xsl:apply-templates
> select="following-sibling::Item[1]">
> <xsl:with-param name="cur-position"
> select="$new-position"/>
> </xsl:apply-templates>
> <xsl:if test="not(following-sibling::Item[1])">
> <xsl:call-template name="pad-space">
> <xsl:with-param name="position"
> select="$new-position"/>
> </xsl:call-template>
> <xsl:text>
> </xsl:text>
> </xsl:if>
> </xsltherwise>
> </xsl:choose>
> </xsl:template>
> <xsl:template name="pad-space">
> <xslaram name="position"/>
> <xsl:variable name="left"
> select="$max-length - $position"/>
> <xsl:if test="0 &lt; $left">
> <xsl:value-of select="$pad-with"/>
> <xsl:call-template name="pad-space">
> <xsl:with-param name="position"
> select="$position + 1"/>
> </xsl:call-template>
> </xsl:if>
> </xsl:template>
> </xsl:stylesheet>
>
> Not tested on anything but the sample document provided by
> the OP. Note that on large documents it is likely to barf
> all over the stack and die horrible death. So I would
> strongly advise against deploying it in production
> environments without some serious tinkering beforehand
> (preferrably the tinkering would involve rewriting the
> transformation in a language more suitable for the task).
>
> --
> Pavel Lepin
>



 
Reply With Quote
 
p.lepin@ctncorp.com
Guest
Posts: n/a
 
      02-01-2007
On Feb 1, 3:50 am, "Dimitre Novatchev"
<dimit...@tpg.com.au> wrote:
> > Note that on large documents it is likely to barf
> > all over the stack and die horrible death. So I would
> > strongly advise against deploying it in production

>
> Not necessarily.


I was talking specifically about the implementation I
provided.

> One can use a DVC (Divide and Conquer) approach, which
> requires as little as Log2(N) maximum stack depth.


Wouldn't there be certain problems with implementing DVC
for this task? The position of every Item depends on all
previous Items after all. Tail recursion would seem like a
better approach to me, but I not sure there are any XSLT
processors to date that can optimize it away. (Are there,
by the way?)

--
Pavel Lepin

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
formating of text file Dips Java 2 05-19-2005 11:23 AM
file formating...help needed comp_novice C Programming 3 02-04-2005 03:00 PM
ANN: New low-cost XML Editor, XSLT Editor, XSLT Debugger, DTD/Schema Editor Stylus Studio Java 0 08-03-2004 03:53 PM
formating pipe delimited file J Perl Misc 8 02-16-2004 04:03 AM
[XSLT]Passing values from Javascript to a XSLT variable Benjamin Hillsley XML 3 09-25-2003 04:50 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57