1

I've been doing a lot of work trying to figure out how to view a XML file (on Internet Explorer) using a style sheet, and retain carriage returns / linefeeds from the document.

I did make it work, but didn't want to use tons of CDATA with [br/] all over my XML file. I was hoping to use the saved carriage returns in the XML text file.

I saw other examples such as this one: how to convert NEWLINE into <BR/> with XSLT? but I'm not very good at XML/XSL and couldn't figure out how to make it work right. Everything I did it had the placed a "& lt;br/& gt;" or a CR/LF but not a < br > that the browser could understand.


XSL file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <body style="font-family:verdana;">
            <h2>Example</h2>

            <table border="1" bordercolor="#000000" cellspacing="0">
                <tr bgcolor="#000000" style="color:#FFFFFF;text-align:left;font-size:80%">
                    <th>#</th>
                    <th>Has <![CDATA["CDATA[<br/>]"]]> (It Works)</th>
                    <th>Has <![CDATA["&#xA;"]]> (Want this one as worst case)</th>
                    <th>Has Carriage Return (Want this one to work)</th>
                </tr> 

                <xsl:for-each select="report/test">
                    <tr style="text-align:left;font-size:80%">
                        <xsl:choose>
                            <xsl:when test="@type = 'append_text'">
                                <td><b><xsl:value-of select="text"/></b></td>
                            </xsl:when>
                            <xsl:when test="@type = 'test_step'">                   
                                <td id="ref{num}"><xsl:value-of select="num"/></td>

                                <td><xsl:value-of select="hasBR" disable-output-escaping="yes"/></td>
                                <td><xsl:value-of select="hasXA" disable-output-escaping="yes"/></td>
                                <td><xsl:value-of select="hasCR" disable-output-escaping="yes"/></td>

                            </xsl:when>
                        </xsl:choose>
                    </tr>
                </xsl:for-each>

            </table>


        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

XML file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="51380-200.xsl"?>
    <report>

        <test type="test_step">
            <num>1</num>
            <hasXA>Line 1 &#xA; Line 2 &#xA; Line 3</hasXA>
            <hasBR>Line 1 <![CDATA[<br/>]]> Line 2 <![CDATA[<br/>]]> Line 3</hasBR>
            <hasCR>Line 1
            Line2
            Line3</hasCR>
        </test>

        <test type="test_step">
            <num>2</num>
            <hasXA>Line 1 &#xA; Line 2 &#xA; Line 3</hasXA>
            <hasBR>Line 1 <![CDATA[<br/>]]> Line 2 <![CDATA[<br/>]]> Line 3</hasBR>
            <hasCR>Line 1
            Line2
            Line3</hasCR>
        </test>

        <test type="test_step">
            <num>3</num>
            <hasXA>Line 1 &#xA; Line 2 &#xA; Line 3</hasXA>
            <hasBR>Line 1 <![CDATA[<br/>]]> Line 2 <![CDATA[<br/>]]> Line 3</hasBR>
            <hasCR>Line 1
            Line2
            Line3</hasCR>
        </test>

    </report>

I greatly appreciate the help!

Note, I've been using XSL transform.net to try to make it work. I loaded a version of it on it. http://xsltransform.net/bESZULX

Rhidium
  • 13
  • 3

2 Answers2

0

Assumed that you might want something like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <body style="font-family:verdana;">
            <h2>Example</h2>

            <table border="1" bordercolor="#000000" cellspacing="0">
                <tr bgcolor="#000000" style="color:#FFFFFF;text-align:left;font-size:80%">
                    <th>#</th>
                    <th>Has <![CDATA["CDATA[<br/>]"]]> (It Works)</th>
                    <th>Has <![CDATA["&#xA;"]]> (Want this one as worst case)</th>
                    <th>Has Carriage Return (Want this one to work)</th>
                </tr> 

                <xsl:for-each select="report/test">
                    <tr style="text-align:left;font-size:80%">
                        <xsl:choose>
                            <xsl:when test="@type = 'append_text'">
                                <td><b><xsl:value-of select="text"/></b></td>
                            </xsl:when>
                            <xsl:when test="@type = 'test_step'">                   
                                <td id="ref{num}"><xsl:value-of select="num"/></td>

                                <td><xsl:value-of select="hasBR" disable-output-escaping="yes"/></td>
                                <td><xsl:value-of select="hasXA" disable-output-escaping="yes"/></td>
                                <td>
                                    <xsl:call-template name="insertBreaks">
                                        <xsl:with-param name="pText" select="hasCR" />
                                    </xsl:call-template>
                                </td>
                            </xsl:when>
                        </xsl:choose>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

<xsl:template match="hasCR" name="insertBreaks">
    <xsl:param name="pText" select="." />

    <xsl:choose>
        <xsl:when test="not(contains($pText, '&#xA;'))">
            <xsl:copy-of select="$pText" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="substring-before($pText, '&#xA;')" />
            <br />
            <xsl:call-template name="insertBreaks">
                <xsl:with-param name="pText" select="substring-after($pText, '&#xA;')" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

http://xsltransform.net/eieE3PZ

enter image description here

Vebbie
  • 1,669
  • 2
  • 12
  • 18
  • This looks like it works out the way I want it to. I'll have to work on my actual XSL file that is actually way huger than what I posted. (wanted to keep it simple for finding a solution). Thanks again for the help! – Rhidium Feb 23 '19 at 01:39
  • So from your example, do I need to make a template (ie insertBreaks) for each one? For example if "hasXA" actually had carrage returns like "hasCR", I would need to make a new template "insertBreaks2" targeting "hasXA"? I just tried making one and it worked, but was wondering if there's a simpler way to do it since I have multiple columns I want to perform this ability. Thanks. – Rhidium Feb 23 '19 at 09:16
  • No. That’s not needed. You can match multiple nodes in the same. E.g. ‘ – Vebbie Feb 23 '19 at 09:20
  • I was playing with it and couldn't I just remove the template match ie change `` to ``. Then to call it each via: `` ``? It appears to have works when I tried it. – Rhidium Feb 25 '19 at 21:03
0

Let's split the problem.

The output

You are producing HTML. It has its own rules about preserving line breaks when rendering: inside a td element you would need a br element.

The input

You have an XML document. Nothing prohibits you from using mixed content. Example:

<hasBR>Line 1 <br />Line 2 <br />Line 3</hasBR> 

The transformation

If your aren't going to do any other process over your mixed content, the best solution would be just to copy that. So, instead of

<td><xsl:value-of select="hasBR" disable-output-escaping="yes"/></td>

... use xsl:copy-of instruction like

<td><xsl:copy-of select="hasBR/node()"/></td>

Note: It's posible to keep processing your mixed content if you use the identity transformation pattern. When mixing two XML vocabularies, you must also be very careful about namespaces.

Finally, if your XML input document can't benefit from mixed content then you could always use a recursive template to process your string value like @Vebbie answer. For newer versions of XSLT there are better solutions.

Alejandro
  • 1,882
  • 6
  • 13
  • I was looking at the hasCR for a solution. Vebbie seems to have one that works for me. Since I'm very new to XML XSL stuff, I'm trying to figure this out. If there are better methods, then I'd love to hear about it. – Rhidium Feb 23 '19 at 01:36
  • @Rhidium There are better methods for newer versions of XSLT. I answered your question because I want to stress that there is no good reason for not to use mixed content: if you can serialize an `xA` character you also can serialize an element `
    `
    – Alejandro Feb 23 '19 at 13:16