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 ドキュメントに適用されると(指定されたフラグメントが 1 つの最上位要素にラップされます):

<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 に答える