使用XSLT将字符串通过分号分隔为XML元素



我已经转换了xml:

<import>
    <issue>
        <article>
            <languageVersion>
                <title>some title</title>
                <keywords>keyword1; keyword2; keyword3</keywords>
            </languageVersion>
        </article>
        <article>
            <languageVersion>
                <title>some title</title>
                <keywords>keyword1; keyword2; keyword3</keywords>
            </languageVersion>
        </article>
    </issue>
</import>

现在,我想使用XSLT变换将标签中的所有单词通过semicolon分开,因此目标XML会这样:

<import>
    <issue>
        <article>
            <languageVersion>
                <title>some title</title>
                <keywords>
                    <keyword>keyword1</keyword>
                    <keyword>keyword2</keyword>
                    <keyword>keyword3</keyword>
                </keywords>
            </languageVersion>
        </article>
        <article>
            <languageVersion>
                <title>some title</title>
                <keywords>
                    <keyword>keyword1</keyword>
                    <keyword>keyword2</keyword>
                    <keyword>keyword3</keyword>
                </keywords>
            </languageVersion>
        </article>
        <article>
    </issue>
</import>

如何使用XSLT转换来执行此操作?我已经尝试已经使用了来自那里的代码,但是不幸的是代码正在销毁其余XML元素:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="keywords">
        <keywords>
            <xsl:apply-templates/>
        </keywords>
    </xsl:template>
    <xsl:template match="keywords" name="split">
        <xsl:param name="pText" select="."/>
        <xsl:param name="pItemElementName" select="'keyword'"/>
        <xsl:if test="string-length($pText) > 0">
            <xsl:variable name="vNextItem" select=
      "substring-before(concat($pText, ';'), ';')"/>
            <xsl:element name="{$pItemElementName}">
                <xsl:value-of select="$vNextItem"/>
            </xsl:element>
            <xsl:call-template name="split">
                <xsl:with-param name="pText" select="substring-after($pText, ';')"/>
                <xsl:with-param name="pItemElementName" select="$pItemElementName"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

您有两个匹配keywords的模板,如果它们具有相同的优先级,则将其视为XSLT中的错误。根据规格...

XSLT处理器可能会发出误差的信号;如果没有信号 错误,它必须从匹配模板中从选择中恢复 剩下的规则是在样式表中最后一次发生的规则。

因此,在您的情况下,这只是第二个使用的模板。

但是,您需要做的就是删除第二个模板上的"匹配",以使其仅使其成为命名模板,然后更改第一个直接调用命名模板的模板。您还应该添加身份模板,以照顾现有元素,然后您的工作将完成

尝试此XSLT

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="keywords">
        <xsl:copy>
            <xsl:call-template name="split" />
        </xsl:copy>
    </xsl:template>
    <xsl:template name="split">
        <xsl:param name="pText" select="."/>
        <xsl:param name="pItemElementName" select="'keyword'"/>
        <xsl:if test="string-length($pText) > 0">
            <xsl:variable name="vNextItem" select=
      "substring-before(concat($pText, ';'), ';')"/>
            <xsl:element name="{$pItemElementName}">
                <xsl:value-of select="$vNextItem"/>
            </xsl:element>
            <xsl:call-template name="split">
                <xsl:with-param name="pText" select="substring-after($pText, ';')"/>
                <xsl:with-param name="pItemElementName" select="$pItemElementName"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

相关内容

  • 没有找到相关文章

最新更新