将字符串拆分为不同的元素

时间:2018-02-27 10:09:10

标签: xslt xslt-1.0

我有带有子字符串的文本元素的xml,可以通过模式§\d+匹配:

<root>
  <item>text-one §42 text-two</item>
</root>

是否可以使用xslt-1.0将其转换为分离的元素:

<p>
  <xsl:text>text-one </xsl:text>
  <a href="/link#42>§42</a>
  <xsl:text> text-two</xsl:text>
</p>

1 个答案:

答案 0 :(得分:1)

只要

,此样式表就能满足您的需求
  • 一个空格可以作为段号

    的结束分隔符

    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="root/*"/>
        </root>
    </xsl:template>
    
    <xsl:template match="item">
        <p>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="."/>
            </xsl:call-template>
        </p>
    </xsl:template>
    
    <xsl:template name="tokenize">
        <xsl:param name="text"/>
        <xsl:choose>
            <xsl:when test="contains($text, '§')">
                <xsl:if test="substring-before($text, '§') != ''">
                    <text><xsl:value-of select="substring-before($text, '§')"/></text>
                </xsl:if>
                <xsl:call-template name="buildParagraphAnchor">
                    <xsl:with-param name="tail" select="substring-after($text, '§')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <text><xsl:value-of select="$text"/></text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template name="buildParagraphAnchor">
        <xsl:param name="tail"/>
        <xsl:variable name="paragraphNumber">
            <xsl:choose>
                <xsl:when test="contains($tail, ' ')">
                    <xsl:value-of select="substring-before($tail, ' ')"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$tail"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <a href="/link#{$paragraphNumber}"><xsl:text>§</xsl:text><xsl:value-of select="$paragraphNumber"/></a>
        <xsl:if test="contains($tail, ' ')">
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="concat(' ', substring-after($tail, ' '))"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    

它转换

<root>
    <item>text-one §42 text-two §45</item>
    <item>§50 text-three</item>
    <item>text-four</item>
</root>

进入

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <p>
        <text>text-one </text>
        <a href="/link#42">§42</a>
        <text> text-two </text>
        <a href="/link#45">§45</a>
    </p>
    <p>
        <a href="/link#50">§50</a>
        <text> text-three</text>
    </p>
    <p>
        <text>text-four</text>
    </p>
</root>
  • 这两个模板以递归方式相互调用(非常典型的XSL)
  • tokenize模板将基于段落符号的内容拆分为头尾(符号前/后)
  • buildParagraphAnchor根据空白
  • 再次将尾部分成头尾
  • 通过这种方式,我们可以将块放入正确的元素
  • 当段落符号是第一个字符等时,其余部分是特殊处理

因此,它将item内容拆分为块,并将部分放入所需的元素中。