我已经转换了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转换用分号分隔标签中的所有单词,所以目标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转换执行此操作?我已经尝试使用there中的代码,但不幸的是代码正在破坏其余的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>
答案 0 :(得分:3)
您有两个匹配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>