1

我希望包含来自 CSV 格式的 XML 元素的数据。

具有讽刺意味的是,输出是一个 CSV 文件。

真正的问题是 CSV 格式允许 4 个关键字。

,,,,,,one,two,three,four,,,,,,     OK
,,,,,,one,two,three,four,five,,,,, WRONG
,,,,,,one,two,,,,,,,,              OK
,,,,,,,,,,,,,,,                    OK

因此,通常的嫌疑人<value-of select="keywords"/>不会工作,因为元素中的值的数量是可变的,最常见的是 NONE 有时是 3 到 5 个条目。

<keywords>one,two,three,four</keywords>
<keywords>one,two,three,four,five</keywords>
<keywords>one,two</keywords>
<keywords></keywords>

有没有办法使用 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="','"/>
4

2 回答 2

1

I. 这是一个简单的 XSLT 2.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>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时(提供的片段包装到单个顶部元素中):

<t>
    <keywords>one,two,three,four</keywords>
    <keywords>one,two,three,four,five</keywords>
    <keywords>one,two</keywords>
    <keywords></keywords>
</t>

产生了想要的正确结果:

one,two,three,four
one,two,three,four
one,two

二、非递归 XSLT 1.0 解决方案

这个 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>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

当应用于同一个 XML 文档(上图)时,会产生所需的正确结果

one,two,three,four
one,two,three,four
one,two
于 2013-05-15T03:03:13.050 回答
1

这是一个简单的递归版本:

<xsl:template name="cvsmaxkey">
    <xsl:param name="keys" />
    <xsl:param name="nrofkeys" /> 
    <xsl:param name="pos" />
    <xsl:if test="$pos &lt;= $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>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="/">
    <xsl:apply-templates select="//keywords"/>
</xsl:template>

生成以下输出(使用 const 分隔符 (,) 数量:

one,two,three,four
one,two,three,four
one,two,,
,,,
于 2013-05-15T08:12:02.823 回答