Interpreting newlines with xsl:text?

2019-01-27 13:41发布

问题:

I have an XSL stylesheet with content in an xsl:text node like this:

<xsl:text>
foo
bar
baz
</xsl:text>

The stylesheet itself is a text file with "unix-style" newline line terminators. I invoke this stylesheet on Windows as well as unix-like platforms. It would be nice to have the output conform to the conventions of the platform on which it is invoked.

When I run this stylesheet on Windows, the output has carriage return/newline pairs for everything except the contents of the xsl:text node.

Can I instruct the XSLT processor to translate the newline characters in the content of the xsl:text node into platform specific end-of-lines?

More context: I'm invoking the stylesheet from the Apache Ant 1.7.1 XSLT task like this:

<xslt in="in.xml" out="out.xml" style="stylesheet.xsl"/>

The stylesheet header currently looks like this:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xalan="http://xml.apache.org/xslt"
    exclude-result-prefixes="xalan">
    <!-- contents elided -->
</xsl:stylesheet>

回答1:

You could define a parameter for the stylesheet like so:

<xsl:param name="br">
    <xsl:text>&#10;</xsl:text>
</xsl:param>

and pass in the appropriate end of line character(s) by using a nested param element in your Ant script. The default in this example would be a Unix-style newline, of course. I think to output the value, you'd have to use:

<xsl:copy-of select="$br"/>

It's verbose, but it works.



回答2:

If you are calling the transform from Ant, then you can test for the OS using a conditional task with a test for the OS family:

  <condition property="linebreak" value="&#xD;&#xa;">
      <os family="windows"/>
  </condition>
  <condition property="linebreak" value="&#xa;">
      <os family="unix"/>
  </condition>

Then pass that parameter to the XSLT to signal which newline character(s) you want to use.

 <xslt in="data.xml" out="${out.dir}/out.xml">
   <param name="linebreak" expression="${linebreak}" />
 </xslt>


回答3:

Im not sure how to do the correct newlines automatically (it may depend on the xslt processor you are using), but you may be able to force the newlines in the contents of your text node. \r\n is &#xD; &#xA;, \n is &#xA;, e.g. you'd use:

<xsl:text>foo&#xD;&#xa;bar&#xD;&#xa;</xsl:text> to get the output you're looking for.



回答4:

Well, I got mine to work (using Saxon) with a combination of 2 ideas above:

<xsl:param name="br">
        <xsl:text>&#xD;&#xa;</xsl:text>
</xsl:param>

and then using line(s) like these where needed.

<xsl:value-of select="$br" />

Here is my full (but slimline) xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!--<xsl:strip-space elements="*" />-->
  <xsl:output method="text" />
  <!-- <xsl:preserve-space elements="*"/>-->
<xsl:param name="br">
        <xsl:text>&#xD;&#xa;</xsl:text>
</xsl:param>


  <!--  -->
  <xsl:template match="/">


    <xsl:for-each select="//root/Item">

        <xsl:value-of select="@Name" /> <!-- Your xpath will vary of course! -->
        <xsl:value-of select="$br" />

    </xsl:for-each>

</xsl:template>

Again, I am using Saxon %ProgramFiles%\SaxonHE\bin\Transform.exe on a windows 7 x64 machine.