我已经转换了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>