linebreaks and indents in TEXT output

Here should go questions about transforming XML with XSLT and FOP.
GregWait42
Posts: 8
Joined: Wed Feb 19, 2020 10:52 pm

linebreaks and indents in TEXT output

Post by GregWait42 » Thu Sep 10, 2020 1:30 am

I have a DITA document for **TEXT** output that contains msg elements like this:

Code: Select all

<msg>
  <msgId>
 
     <msgNumber>1234567</msgNumber>

  </msgId>
  <msgText>The variations of this message are explained below. <?linebreak?> -option one. <?linebreak?> -option two. 
  </msgText>
</msg>
I need the output of msgText to break at each <?linebreak?> and to indent the result. Because the output is simple text my hands are tied in a lot of ways. Here’s a sample of the desired output:

-----------------------------------------------------------------
1234567 The variations of this message are explained below.
                                                                 
        -option one.
                                                                 
       -option two.


I’ve managed to force the line breaks and indent the subsequent lines, BUT where any segment of msgText is long enough to wrap to the next line, the wrapped portion is not indented…

-----------------------------------------------------------------
1234567 The variations of this message are explained below. This
part wraps and needs to be indented.
                                                                
        -option one. When these segments are long enough to wrap
this part wraps and needs to be indented.
                                                                
       -option two.

Here’s the code I have that makes it work to the extent it does:

Code: Select all

<xsl:template match="*[contains(@class, ' msg/msgText ')]">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="processing-instruction()[name() = 'linebreak']">
  <!-- This forces a linebreak by filling an entire line with non-breaking-spaces, and tacking on 
     a normal space to allow content that follows to wrap to the next line. -->
   <text>
      <xsl:for-each select="1 to $LINELENGTH">&#160;</xsl:for-each>
      <xsl:text> </xsl:text>
  </text>
     <!-- This indents the first line of the next segment of msgText. -->
     <text>&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text>
</xsl:template>
I’m close to the solution on this, but I can’t think of a way to directly manipulate the segments of msgText since I’m breaking it into segments when the focus is on <?linebreak?>.

Any thoughts, ideas, lifelines gratefully accepted. Thanks!

Radu
Posts: 7428
Joined: Fri Jul 09, 2004 5:18 pm

Re: linebreaks and indents in TEXT output

Post by Radu » Thu Sep 10, 2020 6:52 am

Hi Greg,

That particular "msgText" does not appear to be part of the DITA specification. How about if you add in your DITA specialization another element named "msgPreserveText" which would extend the DITA <codeblock> base element?

Coming back to your stylesheet, maybe instead of matching the PIs you could match the text nodes before each PI:

Code: Select all

    <xsl:template match="text()[following-sibling::node()[1][processing-instruction()[name() = 'linebreak']]]">
        
        
    </xsl:template>
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

GregWait42
Posts: 8
Joined: Wed Feb 19, 2020 10:52 pm

Re: linebreaks and indents in TEXT output

Post by GregWait42 » Thu Sep 10, 2020 11:05 pm

Radu -

Thanks for your reply. Unfortunately, unless I'm missing some nuance or piece you expected me to know to fill in, your code simply selects the entire msgText text node as a single entity in essentially the same way <xsl:template match="*[contains(@class, ' msg/msgText ')]"> does.

In testing, when I replace my processing-instruction template with your suggestion and add "matched" to indicate its impact...

Code: Select all

<xsl:template match="*[contains(@class, ' msg/msgText ')]">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()[following-sibling::node()[1][processing-instruction()[name() = 'linebreak']]]">
        <text>matched</text>
</xsl:template>
I get this result:

-----------------------------------------------------------------
1234567 matchedThe variations of this message are explained below. -option one. -option two.


What I hoped/need as a result is:

-----------------------------------------------------------------
1234567 matchedThe variations of this message are explained below. matched-option one. matched-option two.


If I can break msgText into a number of separate entities I can handle uniquely, I'll be able to achieve the desired result. Unless I'm implementing it incorrectly, your solution returns the text of msgText in its entirety.

Thanks!

Radu
Posts: 7428
Joined: Fri Jul 09, 2004 5:18 pm

Re: linebreaks and indents in TEXT output

Post by Radu » Fri Sep 11, 2020 8:33 am

Hi,

Sorry, should have checked my XSLT bit before offering it as an example.
This should work to match all individual pieces of text immediately followed by that processing instruction:

Code: Select all

  <xsl:template match="msgText/text()[following-sibling::node()[1][self::processing-instruction()][name() = 'linebreak']]">
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Radu
Posts: 7428
Joined: Fri Jul 09, 2004 5:18 pm

Re: linebreaks and indents in TEXT output

Post by Radu » Fri Sep 11, 2020 8:38 am

Or maybe match text which is after a processing instruction:

Code: Select all

    <xsl:template match="msgText/text()[preceding-sibling::node()[1][self::processing-instruction()][name() = 'linebreak']]">
whatever suits you better.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

GregWait42
Posts: 8
Joined: Wed Feb 19, 2020 10:52 pm

Re: linebreaks and indents in TEXT output

Post by GregWait42 » Sat Sep 12, 2020 12:37 am

Radu,

I think you've got me on the right path. With a few tweaks I have it breaking up the text so I can handle the first segment separately from those that follow. Now I need to figure out a way to indent any part of each segment that wraps to the next line, but you've got me moving forward. Thanks!

Greg

Post Reply