HTML 使用 XSLT 换行的新行

New Lines to HTML Line Breaks Using XSLT

我有以下 XML:

<RichText>
    Text
    Text
    Text
</RichText>

我想使用 XSLT 1.0(2.0,如果我真的必须的话)输出以下 HTML:

<p>
    Text<br/>
    Text<br/>
    Text
</p>

我试过使用以下接近的 XSL:

<xsl:template match="text()">
  <xsl:param name="text" select="."/>

  <!-- Because we would rely on $text containing a line break when using 
      substring-before($text,'&#10;') and the last line might not have a
      trailing line break, we append one before doing substring-before().  -->
  <xsl:value-of select="substring-before(concat($text,'&#10;'),'&#10;')"/>
  <br/>

  <xsl:if test="contains($text,'&#10;')">
    <xsl:apply-templates select=".">
      <xsl:with-param name="text" select="substring-after($text,'&#10;')"/>
    </xsl:apply-templates>
  </xsl:if>
<xsl:template>

这输出:

<p><br>                  
    Text<br>                  
    Text<br>                  
    Text<br>
<br></p>

尝试以下脚本:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

  <xsl:template match="RichText">
    <p>
      <xsl:variable name="txt" select="tokenize(., '&#xA;')"/>
      <xsl:variable name="len" select="count($txt)"/>
      <xsl:for-each select="subsequence($txt, 2, $len - 2)">
        <xsl:value-of select="replace(replace(.,'\s+$',''),'^\s+','')"/>
        <xsl:if test="position() &lt; last()">
          <xsl:text disable-output-escaping="yes">&lt;br/&gt;</xsl:text>
        </xsl:if>
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
    </p>
  </xsl:template>

</xsl:transform>

我使用 XSLT 2.0,作为一个更易于编写的版本。

可以使用 XSLT 1.0 重写它,但必须使用等效的 1.0 解决方案:

  • 标记化,
  • 子序列,
  • 和修剪。

对于您的 XSLT 1.0 解决方案,我认为您只需要一些 xsl:if 测试来测试您正在处理的当前行前后是否有非白色 space 文本。

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" />

<xsl:template match="RichText">
  <p><xsl:apply-templates /></p>
</xsl:template>

<xsl:template match="text()">
   <xsl:param name="text" select="."/>

   <xsl:variable name="startText" select="substring-before(concat($text,'&#10;'),'&#10;')" />
   <xsl:variable name="nextText" select="substring-after($text,'&#10;')"/>
   <xsl:if test="normalize-space($startText)">
       <xsl:value-of select="$startText"/>
      <xsl:if test="normalize-space($nextText)">
         <br />
      </xsl:if>
   </xsl:if>

   <xsl:if test="contains($text,'&#10;')">
      <xsl:apply-templates select=".">
         <xsl:with-param name="text" select="$nextText"/>
      </xsl:apply-templates>
   </xsl:if>
</xsl:template>
</xsl:stylesheet>