Создание абзацев с помощью xsl

Эй, я бродил, есть ли у кого-нибудь предложения о том, как взять новые строки из файла XML и преобразовать их в абзацы с преобразованием XSL.

Вот как выглядит структура XML:

<?xml version="1.0" encoding="ISO-8859-1"?>

<document>
<book>
<issue>1</issue>
<body>
“Dude, I can't believe you fed it to your cat.  That's crazy!” 

“Yeah, dude, he just cuddled up next to me and started purring.”

“Then what did he do?”

“He just kept purring, man.  He's been purring non-stop for like two weeks now.  I can't even sleep.”  
</body>
</book>
</document>

А вот копия листа XSL, который я использую для преобразования.

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

<body style="font-family:Arial;font-size:12pt;">

<xsl:for-each select="document/book">

<div style="color:red; padding:4px;">
<span style="font-weight:bold">
</span> Chapter 
<xsl:value-of select="info/issue"/>
</div>
<div style="margin-left:10px; margin-bottom:1em; margin-right:25px; font-size:10pt;">
<span>
<xsl:value-of select="body"/>
</span>
</div>

</xsl:for-each>
</body>
</html>

Опять же, мой вопрос касается того, какие команды использовать для сохранения структуры абзаца с использованием существующего документа XSL.

Спасибо, Э


person user633264    schedule 31.03.2011    source источник
comment
@ user633264: Самый простой подход — использовать xsl:appy-templates select="body" вместо xsl:value-of, а затем размечать текстовые узлы символом новой строки (помните, что это нормализовано до #xA;), добавляя элементы br или перенося их в элементы p. Здесь есть много примеров.   -  person    schedule 31.03.2011
comment
Хороший вопрос, +1. Смотрите мой ответ для полного, короткого и простого решения.   -  person Dimitre Novatchev    schedule 01.04.2011


Ответы (2)


Это преобразование:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

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

  <xsl:if test="string-length($pText)">
   <xsl:choose>
    <xsl:when test="not(contains($pText, '&#xA;'))">
      <xsl:value-of select="$pText"/>
    </xsl:when>
    <xsl:otherwise>
     <p>
       <xsl:value-of select=
       "substring-before($pText,'&#xA;')"/>
     </p>
     <xsl:call-template name="replaceNL">
      <xsl:with-param name="pText" select=
       "substring-after($pText,'&#xA;')"/>
     </xsl:call-template>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу:

<document>
<book>
<issue>1</issue>
<body>
“Dude, I can't believe you fed it to your cat.  That's crazy!”

“Yeah, dude, he just cuddled up next to me and started purring.”

“Then what did he do?”  “He just kept purring, man.  He's been purring non-stop for like two weeks now.  I can't even sleep.”
</body>
</book>
</document>

выдает желаемый правильный результат:

<document>
   <book>
      <issue>1</issue>
      <body>
         <p/>
         <p>“Dude, I can't believe you fed it to your cat.  That's crazy!”</p>
         <p>        </p>
         <p>“Yeah, dude, he just cuddled up next to me and started purring.”</p>
         <p>        </p>
         <p>“Then what did he do?”  “He just kept purring, man.  He's been purring non-stop for like two weeks now.  I can't even sleep.”</p>
      </body>
   </book>
</document>

Объяснение: правило идентификации + рекурсивный именованный шаблон для переноса в p каждой текстовой подстроки, окруженной символами NL.

person Dimitre Novatchev    schedule 01.04.2011
comment
Спасибо за помощь. Он отлично работает и поможет мне лучше понять XSL. - person user633264; 02.04.2011
comment
@ user633264: Рад, что мое решение отлично работает и полезно для вас. Здесь, в SO, по официальному этикету ожидается, что оригинальный постер примет лучший ответ. Это легко сделать, нажав на зеленую галочку рядом с ответом. :) - person Dimitre Novatchev; 02.04.2011

Взгляните на FXSL 1.2, http://sourceforge.net/projects/fxsl/. Я не могу ответить за качество и полезность этого проекта, но, по крайней мере, он содержит много материала и кое-что, что может вам понадобиться.

В противном случае атака заключалась бы в выборе текстового узла тела и рекурсивном создании новых текстовых узлов с использованием функций substring-before и substring-after и окружении каждого нового текстового узла узлом «p». Рекурсивный бит, вероятно, является сложной частью, но в коде, упомянутом выше, есть много примеров.

person forty-two    schedule 31.03.2011