2016-02-16 3 views
0

Учитывая источник 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> 

Может ли кто-нибудь помочь мне?

+0

Можете ли вы использовать процессор XSLT 2.0, например Saxon 9? –

+0

Да, я в настоящее время использую saxon9he – ChrisV

ответ

1

С вашими отредактированными требованиями я думаю, что лучше сделать преобразование с двумя проходами, где мы сначала преобразуем символы строки в текстовые узлы в элемент (я использовал элемент «lb»), чтобы затем группировать эти элементы, используя 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.

+0

@ChrisV, пожалуйста, отредактируйте свой вопрос и предоставите новые входные образцы и запрошенные результаты в вопросе, правильно обозначенные как образцы кода, тогда их легче прочитать и понять, чего вы хотите достичь , –

+0

Я сделал это. – ChrisV

+0

@ChrisV, я отредактировал ответ и предоставил новый подход, который должен лучше справляться с вашими требованиями. Он по-прежнему использует 'for-each-group group-start-with', но преобразует символы разрыва строки в первый проход в элементы' lb', чтобы лучше использовать конструкцию группировки. –

Смежные вопросы