如何拆分和包装混合内容

时间:2016-02-16 13:28:37

标签: xslt

给出源xml:

<margetekst>
    Article 36<em>bis</em>
    Article 40
</margetekst>
<margetekst>
    test 1
</margetekst>
<margetekst>
    test 2a
    test 2b
</margetekst>
<margetekst>
    test <em>3a</em>
    test 3b
</margetekst>
<margetekst>
    test <em>4</em>a and some more text
    test <em>4</em>b
</margetekst>

我需要以下结果:

<margetekst>
    <div>Article 36<em>bis</em></div>
    <div>Article 40</div>
</margetekst>
<margetekst>
    <div>test 1</div>
</margetekst>
<margetekst>
    <div>test 2a</div>
    <div>test 2b</div>
</margetekst>
<margetekst>
    <div>test <em>3a</em></div>
    <div>test 3b</div>
</margetekst>
<margetekst>
    <div>test <em>4</em>a and some more text</div>
    <div>test <em>4</em>b</div>
</margetekst>

我在这个网站上找到了在换行符上拆分文本的解决方案,当<margetekst>的内容只是一个字符串而不是混合内容时,这种方法很有效(结果是:<div>Article 36</div><em>bis</em><div>...</div> )。这是我目前使用的代码:

<xsl:template match="margetekst/text()" mode="paragraafstijlen">
    <xsl:call-template name="div_insert">
        <xsl:with-param name="pText" select="."/>
    </xsl:call-template>
</xsl:template>
<xsl:template match="text()" name="div_insert">
    <xsl:param name="pText" select="."/>
    <xsl:choose>
        <xsl:when test="not(contains($pText, '&#xA;'))">
            <div><xsl:copy-of select="$pText"/></div>
        </xsl:when>
        <xsl:otherwise>
            <div><xsl:value-of select="substring-before($pText, '&#xA;')"/></div>
            <xsl:call-template name="div_insert">
                <xsl:with-param name="pText" select="substring-after($pText, '&#xA;')"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

根据您编辑的要求,我认为最好先进行两遍转换,首先将文本节点中的任何换行符转换为元素(我使用了&#39; lb&#39;元素)然后再进行分组使用xsl:for-each-group group-starting-with="lb"

的元素
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:output method="html" indent="yes"/>

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

<xsl:template match="margetekst">
  <margetekst>
    <xsl:variable name="lbs">
        <xsl:apply-templates mode="lb-char-to-lb-el"/>
    </xsl:variable>
    <xsl:for-each-group select="$lbs/node()" group-starting-with="lb">
        <xsl:if test="not(self::lb and count(current-group()) eq 1)">
            <div>
                <xsl:apply-templates select="current-group()[position() gt 1]"/>
            </div>                
        </xsl:if>
    </xsl:for-each-group>
  </margetekst>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="normalize-space()"/>
</xsl:template>

<xsl:template match="text()[contains(., '&#10;')]" mode="lb-char-to-lb-el">
  <xsl:analyze-string select="." regex="\n">
      <xsl:matching-substring>
          <lb/>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
          <xsl:value-of select="."/>
      </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

在线示例位于http://xsltransform.net/bFN1y9Q,它会转换

<root>
<margetekst>
    Article 36<em>bis</em>
    Article 40
</margetekst>
<margetekst>
    test 1
</margetekst>
<margetekst>
    test 2a
    test 2b
</margetekst>
<margetekst>
    test <em>3a</em>
    test 3b
</margetekst>
<margetekst>
    test <em>4</em>a and some more text
    test <em>4</em>b
</margetekst>
</root>

进入

<root>
   <margetekst>
      <div>Article 36<em>bis</em></div>
      <div>Article 40</div>
   </margetekst>
   <margetekst>
      <div>test 1</div>
   </margetekst>
   <margetekst>
      <div>test 2a</div>
      <div>test 2b</div>
   </margetekst>
   <margetekst>
      <div>test<em>3a</em></div>
      <div>test 3b</div>
   </margetekst>
   <margetekst>
      <div>test<em>4</em>a and some more text
      </div>
      <div>test<em>4</em>b
      </div>
   </margetekst>
</root>

我认为所有div包装都是必需的。