XSLT - add <p> into text strings instead of \n

爱⌒轻易说出口 提交于 2019-12-24 04:11:03

问题


I have an XML document like this:

<xml>
  <item>
    <title>Article 1</title>
    <text><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.

Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.

Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.]]></text>
  </item>
</xml>

Where there are empty lines between the "paragraphs".

And I need to use XSLT transformation where the element will have each paragraph of text between < p > and < / p >. So my desired output would be like:

<h2>Article 1</h2>    
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p>
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p>
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p>

So far I have an XSLT which looks like this:

<xsl:template match="/">
        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
                <title>Page title</title>
            </head>
            <body>
                <h1>Table of contents</h1>
                <ol>
                <xsl:for-each select="xml/item>
                        <li><xsl:value-of select="./title"/></li>
                </xsl:for-each>
                </ol>
                <hr/>
                <xsl:for-each select="xml/item">
                    <h2><xsl:value-of select="./title"/></h2>
                    <xsl:value-of select="./text" disable-output-escaping="yes"/>
                </xsl:for-each>
            </body>
        </html>
</xsl:template>

How to deal with replacements of \n on the right places with paragraph HTML tags? I checked similar questions here, but I'm obviously not able to implement them to my problem.


回答1:


With XSLT 2.0, you can use a regular expression to tokenize your string.

To do so, replace your <xsl:value-of> by:

<xsl:analyze-string select="text" regex="&#xa;">
    <xsl:non-matching-substring>
        <p>
            <xsl:value-of select="."/>
        </p>
    </xsl:non-matching-substring>
</xsl:analyze-string>

In XSLT 1.0, you'd have to define a template that will be called recursively and generates a <p> element for the substring before the first linefeed.




回答2:


If you have to use XSLT 1.0, the following named template can do the job:

<xsl:template name="replace-nl">
  <xsl:param name="str"/>
  <xsl:if test="$str">
    <xsl:variable name="before" select="substring-before($str, '&#10;')"/>
    <xsl:variable name="after" select="substring-after($str, '&#10;')"/>      
    <p>
      <xsl:choose>
        <xsl:when test="$before">
          <xsl:value-of select="normalize-space($before)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="normalize-space($str)"/>
        </xsl:otherwise>
      </xsl:choose>
    </p>
    <xsl:call-template name="replace-nl">
      <xsl:with-param name="str" select="$after"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Just call it instead of xsl:value-of where you want the newline characters to be replaced, e.g.:

<xsl:for-each select="xml/item">
  ...
  <xsl:call-template name="replace-nl">
    <xsl:with-param name="str" select="text"/>
  </xsl:call-template>                    
</xsl:for-each>


来源:https://stackoverflow.com/questions/10671444/xslt-add-p-into-text-strings-instead-of-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!