在特定标记的位置使用XSLT 1.0拆分XML,并在整个结果中维护HTML标记

时间:2014-06-21 18:49:44

标签: html xml xslt

我需要通过在<hr/>标记处拆分来转换以下XML。然后,拆分两侧的内容应存储为params,并在单独的div中输出。

我遇到了几个问题:

1)我似乎无法使用<hr/>标记作为此分隔符。我假设由于解析器在设置新参数之前剥离了标签?这有解决方法吗?我确实可以控制<bodyText>节点内的XM​​L输出,虽然我可以使用指定的字符串,但<hr/>标记可以提供更可靠的标记维护。

2)虽然<xsl:copy-of select="$desc"/>生成HTML标记完整(我需要)的完整内容,但$shortDesc$longDesc都返回裸/剥离的文本内容。如何保留HTML标记?

基本上我需要在<hr/>标记处拆分XML,然后将之前和之后的内容复制到标记完整的单独div中。

我已经看到一些帖子的挑战非常接近这个,但每个帖子都差异很大,以至于我无法解决。

XML:

<bodyText>
  <p>Lorem Ipsum Short</p>
  <hr/>
  <p>Lorem Ipsum Long</p>
</bodyText>

*请注意,XML Feed是管理员生成的,所以这只是一个基本的例子。实际的Feed不可靠,只有<hr/>才能进行拆分。

XSL:

<xsl:template name="ExpandContent_main">    
  <xsl:param name="desc" select="/bodyText"/>
  <xsl:param name="separator" select="'<hr/>'"/>
  <xsl:param name="shortDesc" select="substring-before($desc, $separator)"/>
  <xsl:param name="longDesc" select="substring-after($desc, $separator)"/>
  <div class="short-description">
    <xsl:copy-of select="$shortDesc"/>
  </div>
  <div class="long-description">
    <xsl:copy-of select="$longDesc"/>
  </div>
</xsl:template>

预期产出:

<div class="short-description">
  <p>Lorem Ipsum Short</p>
</div>
<div class="long-description">
  <p>Lorem Ipsum Long</p>
</div>

2 个答案:

答案 0 :(得分:3)

您的错误在于您尝试在节点上使用字符串函数。现在,我认为你不需要一个命名模板。请考虑以下样式表:

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

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

<xsl:template match="bodyText">
    <div class="short-description">
        <xsl:apply-templates select="p[not(preceding-sibling::hr)]"/>
    </div>
    <div class="long-description">
        <xsl:apply-templates select="p[preceding-sibling::hr]"/>
    </div>
 </xsl:template>

</xsl:stylesheet>

当应用于以下测试输入时:

<content>
    <bodyText>
        <p>Lorem <i>Ipsum</i> Short</p>
        <hr/>
        <p>Lorem <b>Ipsum</b> Long</p>
    </bodyText>
</content>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<content>
   <div class="short-description">
      <p>Lorem <i>Ipsum</i> Short</p>
   </div>
   <div class="long-description">
      <p>Lorem <b>Ipsum</b> Long</p>
   </div>
</content>

答案 1 :(得分:2)

<xsl:template match="bodyText"> <div class="short-description"> <xsl:copy-of select="node()[following-sibling::hr]"/> </div> <div class="long-description"> <xsl:copy-of select="node()[preceding-sibling::hr]"/> </div> </xsl:template>