XSLT将mixedContent的字符串拆分部分分析为新元素

时间:2017-06-12 09:13:31

标签: xml xslt xslt-2.0

文字版

XML Source包含名为paragraph的mixedContent-Element。大多数情况下,内容以括号中的数字开头,例如(1)。该数字始终是文本节点的第一个(部分)。

XML Target在名为counter的单独元素中处理此特定数字。

如何以有效的方式处理paragraph

示例号码掩码

(1)
(0...9)
[0...9]
{:digits:}

示例段落来源

<paragraphs>
    <paragraph>(1) text <try>1</try> <italic>italic</italic> stuff</paragraph>
    <paragraph>[2] text <try>2</try> <italic>italic</italic> stuff</paragraph>
    <paragraph>{123} text <try>3</try> <italic>italic</italic> stuff</paragraph>
    <paragraph>text <try>4</try> <italic>italic</italic> stuff</paragraph>   
</paragraphs>

示例段落目标

<paragraphs>    
    <frame>
        <counter>(1)</counter>
        <paragraph>text <try>1</try> <italic>italic</italic> stuff</paragraph>
    </frame>
    <frame>
        <counter>[2]</counter>
        <paragraph>text <try>2</try> <italic>italic</italic> stuff</paragraph>
    </frame>
    <frame>
        <counter>{123}</counter>
        <paragraph>text <try>3</try> <italic>italic</italic> stuff</paragraph>
    </frame>
    <frame>
        <paragraph>text <try>4</try> <italic>italic</italic> stuff</paragraph>
    </frame>
 </paragraphs>

不是(功能)部分

<xsl:template match="paragraph">
    <frame>
        <xsl:analyze-string select="." regex="(^[^\s]+)"><!-- TODO: select digits instead of the first whitespace! -->
            <xsl:matching-substring>
                <xsl:element name="counter">
                    <xsl:value-of select="regex-group(1)" />
                </xsl:element>
            </xsl:matching-substring>
        </xsl:analyze-string>
        <paragraph>
            <xsl:apply-templates/><!-- TODO: everything but not the part of regex-group(1) + whitespace-character -->
        </paragraph>
    </frame>
</xsl:template>

我停止了这个模板的工作,因为可能有更好的解决方案来解决这个问题。

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

如果您只需要从作为文本节点的第一个子节点中提取这两个部分,那么我认为以下内容是这样做的:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

    <xsl:param name="counter-pattern" as="xs:string">^(\([0-9+]\)|\[[0-9]+\]|\{[0-9]+\})</xsl:param>

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

    <xsl:template match="paragraph">
        <frame>
            <xsl:apply-templates select="." mode="counter"/>
        </frame>
    </xsl:template>

    <xsl:template match="paragraph[node()[1][self::text()[matches(., $counter-pattern)]]]"
        mode="counter">
        <xsl:variable name="components" as="xs:string*">
            <xsl:analyze-string select="node()[1]" regex="{$counter-pattern}">
                <xsl:matching-substring>
                    <xsl:sequence select="."/>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:sequence select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </xsl:variable>
        <counter>
            <xsl:value-of select="$components[1]"/>
        </counter>
        <xsl:copy>
            <xsl:value-of select="$components[2]"/>
            <xsl:apply-templates select="node()[position() gt 1]"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

如果计数器和后续文本之间的空格不应显示在段落中,则可能需要使用<xsl:value-of select="replace($components[2], '^\s+', '')"/>而不是<xsl:value-of select="$components[2]"/>

以正则表达式为例,您可能还需要根据自己的需要进行调整。