Xml 在XSLT中拆分逗号分隔的字段,并选择或限制字段数
我希望包含来自CSV格式的XML元素的数据Xml 在XSLT中拆分逗号分隔的字段,并选择或限制字段数,xml,xslt,xpath,Xml,Xslt,Xpath,我希望包含来自CSV格式的XML元素的数据 <xsl:template name="cvsmaxkey"> <xsl:param name="keys" /> <xsl:param name="nrofkeys" /> <xsl:param name="pos" /> <xsl:if test="$pos <= $nrofkeys"> <xsl:if test="$p
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
讽刺的是,输出是一个CSV文件
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
真正的问题是CSV格式允许4个关键字
,,,,,,one,two,three,four,,,,,, OK
,,,,,,one,two,three,four,five,,,,, WRONG
,,,,,,one,two,,,,,,,, OK
,,,,,,,,,,,,,,, OK
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
因此,通常的可疑
不起作用,因为元素中的值的数量是可变的,通常为无,有时为3到5个条目
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
比如
<keywords>one,two,three,four</keywords>
<keywords>one,two,three,four,five</keywords>
<keywords>one,two</keywords>
<keywords></keywords>
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
1,2,3,4
一,二,三,四,五
一,二
是否有任何方法可以使用XSLT将此CSV数组转换为XML元素,然后以每个元素为目标。空值就可以了
<xsl:value-of select="fubar1"/><xsl:value-of select="','"/>
<xsl:value-of select="keyword[1]"/><xsl:value-of select="','"/>
<xsl:value-of select="keyword[2]"/><xsl:value-of select="','"/>
<xsl:value-of select="keyword[3]"/><xsl:value-of select="','"/>
<xsl:value-of select="keyword[4]"/><xsl:value-of select="','"/>
<xsl:value-of select="fubar3"/><xsl:value-of select="','"/>
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
I.这里有一个简单的XSLT2.0解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="text()">
<xsl:value-of select=
"tokenize(., ',')[.][not(position() gt 4)]" separator=","/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
one,two,three,four
one,two,three,four
one,two
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
II。非递归XSLT 1.0解决方案
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
此XSLT 1.0转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vDoc" select="document('')"/>
<xsl:variable name="vNodes"
select="$vDoc//node() | $vDoc//@* | $vDoc//namespace::*"/>
<xsl:template match="text()">
<xsl:variable name="vNorm" select="normalize-space(translate(.,',',' '))"/>
<xsl:variable name="vCount" select=
"string-length($vNorm) -string-length(translate($vNorm, ' ', ''))+1"/>
<xsl:variable name="vTextToPrint">
<xsl:choose>
<xsl:when test="not($vCount >4)"><xsl:value-of select="$vNorm"/></xsl:when>
<xsl:otherwise>
<xsl:for-each select="$vNodes[not(position() > string-length($vNorm))]">
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vheadSubstr" select="substring($vNorm,1,$vPos)"/>
<xsl:if test=
"substring($vNorm, $vPos, 1) = ' '
and
string-length($vheadSubstr)
-
string-length(translate($vheadSubstr, ' ',''))
= 4">
<xsl:value-of select="substring($vNorm,1,$vPos -1)"/>
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="translate($vTextToPrint, ' ', ',')"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
one,two,three,four
one,two,three,four
one,two
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
这里是一个简单的递归版本:
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
<xsl:template name="cvsmaxkey">
<xsl:param name="keys" />
<xsl:param name="nrofkeys" />
<xsl:param name="pos" />
<xsl:if test="$pos <= $nrofkeys">
<xsl:if test="$pos > 1 and $keys">
<xsl:value-of select="','" />
</xsl:if>
<xsl:choose>
<xsl:when test="contains($keys, ',')">
<xsl:value-of select="substring-before($keys,',')" />
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="substring-after($keys,',')" />
<xsl:with-param name="nrofkeys" select="$nrofkeys" />
<xsl:with-param name="pos" select="$pos +1" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$keys">
<xsl:value-of select="$keys" />
<xsl:value-of select="substring(',,,,,,,,,,,', 1,$nrofkeys - $pos)"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="keywords">
<xsl:call-template name="cvsmaxkey">
<xsl:with-param name="keys" select="." />
<xsl:with-param name="nrofkeys" select="4" />
<xsl:with-param name="pos" select="1" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//keywords"/>
</xsl:template>
不清楚您的XML数据是什么样子的。是“如”后面的示例,还是输出?如果您的输入在XML元素中有CSV数据字段,那么听起来您想要使用XSLT做的事情是可能的,但是我更喜欢使用脚本语言来实现这一点。您是否依赖XSLT?首先,非常感谢xml先生。2.0解决方案非常简单,易于遵循。但我必须使用令人困惑的1.0。如何应用一个典型的xml数据,例如@user1869322中的NameAddressone、two、three、four、fivecityxxx,请在提供的xml文档上使用提供的XSLT1.0转换调用XSLT1.0处理器。然后您将得到提供的结果。是的。这很有效。非常感谢。我需要把那些多余的逗号填上。也就是说,不是一,二,而是一,二,@user1869322,不客气。额外的逗号可以在单独的(或其他)指令中输出。就像水力压裂的魅力一样。而且易于实现。它似乎受到
中逗号数量的限制,但在大多数情况下都可以。干杯