2

私はcsvをxmlに変換するためにこのxsltを持っていますが、タグがすべての列で同じであることを除いて、正常に動作します。このように増やす必要があります

<row>
  <column1></column1>
  <column2></column2>
  <column3></column3>
</row>

position() を使用すると、すべての列の名前が column1 に変更されます

<xsl:element name="{concat('column', position())}">

xslt は次のとおりです。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:variable name="LF" select="'&#xA;'"/>
    <!-- template that matches the root node-->
    <xsl:template match="/">
        <root>
            <xsl:call-template name="texttorows">
                <xsl:with-param name="StringToTransform" select="/root"/>
            </xsl:call-template>
        </root>
    </xsl:template>
    <!-- template that actually does the conversion-->
    <xsl:template name="texttorows">
        <!-- import $StringToTransform-->
        <xsl:param name="StringToTransform" select="''"/>
        <xsl:choose>
            <!-- string contains linefeed-->
            <xsl:when test="contains($StringToTransform,$LF)">
                <!-- Get everything up to the first carriage return-->
                <row>
                    <xsl:call-template name="csvtoxml">
                        <xsl:with-param name="StringToTransform" select="substring-before($StringToTransform,$LF)"/>
                    </xsl:call-template>
                </row>
                <!-- repeat for the remainder of the original string-->
                <xsl:call-template name="texttorows">
                    <xsl:with-param name="StringToTransform">
                        <xsl:value-of select="substring-after($StringToTransform,$LF)"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:when>
            <!-- string does not contain newline, so just output it-->
            <xsl:otherwise>
                <row>
                    <xsl:call-template name="csvtoxml">
                        <xsl:with-param name="StringToTransform" select="$StringToTransform"/>
                    </xsl:call-template>
                </row>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="csvtoxml">
        <!-- import $StringToTransform-->
        <xsl:param name="StringToTransform" select="''"/>
        <xsl:choose>
            <!-- string contains linefeed-->
            <xsl:when test="contains($StringToTransform,',')">
                <!-- Get everything up to the first carriage return-->
                <xsl:element name="{concat('column', position())}">
                    <xsl:value-of select="substring-before($StringToTransform,',')"/>
                </xsl:element>
                <!-- repeat for the remainder of the original string-->
                <xsl:call-template name="csvtoxml">
                    <xsl:with-param name="StringToTransform">
                        <xsl:value-of select="substring-after($StringToTransform,',')"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:when>
            <!-- string does not contain newline, so just output it-->
            <xsl:otherwise>
                <column>
                    <xsl:value-of select="$StringToTransform"/>
                </column>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

サンプルの csv は次のとおりです。

<root>
3779490,916705,CS,60,34.89,Sauce/Cholula
5918104,918958,CS,6,20.63,Pasta/Fresh/Cavatelli/6#/Frozen
5064774,920723,CS,10,45.5,Cheese/Oaxaca
3422752,925230,EA,8,69.6,Chipotle/Powder/Ground
5955640,BB171,CS,30,50.7,Butter/Unsalted
5295326,BC110005,CS,6000,54.95,Oil/Olive/Finishing
</root>
4

4 に答える 4

2

OP はおそらく XSLT 1.0 ソリューションを探していますが、興味深いのは XSLT 2.0 ソリューションです。このソリューションでは、 csv-to-xml ライブラリ スタイルシートをここからダウンロードする必要があります。これについては、このブログ エントリで説明しています。

これを入力ドキュメントとして、URI 'gangt.csv' を使用してスタイルシートで参照します (パラメーターを使用するか、必要に応じて調整します)...

ギャング.csv

3779490,916705,CS,60,34.89,Sauce/Cholula
5918104,918958,CS,6,20.63,Pasta/Fresh/Cavatelli/6#/Frozen
5064774,920723,CS,10,45.5,Cheese/Oaxaca
3422752,925230,EA,8,69.6,Chipotle/Powder/Ground
5955640,BB171,CS,30,50.7,Butter/Unsalted
5295326,BC110005,CS,6000,54.95,Oil/Olive/Finishing

スタイルシート

...この XSLT 2.0 スタイルシート...

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:clib="http://www.seanbdurkin.id.au/xslt/csv-to-xml.xslt" 
  xmlns:xcsv="http://www.seanbdurkin.id.au/xslt/xcsv.xsd"
  exclude-result-prefixes="xsl clib xcsv">
<xsl:import href="csv-to-xml.xslt" />
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/" >
 <data-set>
   <xsl:apply-templates select="clib:csv-to-xml('gangt.csv')/xcsv:row" />
 </data-set>
</xsl:template>

<xsl:template match="xcsv:row">
 <row>
   <xsl:apply-templates select="xcsv:value" />
 </row>
</xsl:template>

<xsl:template match="xcsv:value">
 <xsl:element name="column{position()}">
   <xsl:value-of select="." />
 </xsl:element>
</xsl:template>

</xsl:stylesheet>      

出力

...この出力ドキュメントを作成します...

<data-set>
   <row>
      <column1>3779490</column1>
      <column2>916705</column2>
      <column3>CS</column3>
      <column4>60</column4>
      <column5>34.89</column5>
      <column6>Sauce/Cholula</column6>
   </row>
   <row>
      <column1>5918104</column1>
      <column2>918958</column2>
      <column3>CS</column3>
      <column4>6</column4>
      <column5>20.63</column5>
      <column6>Pasta/Fresh/Cavatelli/6#/Frozen</column6>
   </row>
   <row>
      <column1>5064774</column1>
      <column2>920723</column2>
      <column3>CS</column3>
      <column4>10</column4>
      <column5>45.5</column5>
      <column6>Cheese/Oaxaca</column6>
   </row>
   <row>
      <column1>3422752</column1>
      <column2>925230</column2>
      <column3>EA</column3>
      <column4>8</column4>
      <column5>69.6</column5>
      <column6>Chipotle/Powder/Ground</column6>
   </row>
   <row>
      <column1>5955640</column1>
      <column2>BB171</column2>
      <column3>CS</column3>
      <column4>30</column4>
      <column5>50.7</column5>
      <column6>Butter/Unsalted</column6>
   </row>
   <row>
      <column1>5295326</column1>
      <column2>BC110005</column2>
      <column3>CS</column3>
      <column4>6000</column4>
      <column5>54.95</column5>
      <column6>Oil/Olive/Finishing</column6>
   </row>
</data-set>
于 2012-08-18T10:31:37.787 に答える
2

XSLT は非 XML コンテンツを処理できますが、汎用のテキスト変換ツールとして意図されていないようです。その結果、使用できるツールのほとんどは、要素や属性などの XML 情報セット構造を操作するためのものです。テキスト文字列のサポートは少しありますが、それほど多くはありません。は、入力ノードに関してposition()定義されます。

http://www.w3.org/TR/xpath/#section-Node-Set-Functions :

position 関数は、式評価コンテキストからのコンテキスト位置に等しい数値を返します。

http://www.w3.org/TR/xslt#section-Expressions :

コンテキスト位置は、現在のノード リスト内の現在のノードの位置から取得されます。最初の位置は 1

入力は単なるテキスト文字列なので、常に位置 1 にいます。XSLT でこれを行う方法は 1 つだけ考えられます。2回変身。最初の変換では、番号付けされていない列要素を含む基本構造が得られます。2 番目の変換は、列要素に番号を付けます。2 回目は XML ドキュメントからノードを選択しているため、 にposition()は必要な値が含まれているはずです。

于 2012-08-17T22:18:11.730 に答える
2

大きな文字列で呼び出されているように見え、csvtoxmlその文字列を介して再帰的に機能します。position()この場合、一連のノードで作業していないため、機能しません。

代わりに、カウントパラメーターを使用して、目的を達成できる場合があります。

<xsl:template name="csvtoxml">
    <!-- import $StringToTransform-->
    <xsl:param name="StringToTransform" select="''"/>
    <xsl:param name="ColumnNum" select="1"/>
    <xsl:choose>
        <!-- string contains linefeed-->
        <xsl:when test="contains($StringToTransform,',')">
            <!-- Get everything up to the first carriage return-->
            <xsl:element name="{concat('column', $ColumnNum)}">
                <xsl:value-of select="substring-before($StringToTransform,',')"/>
            </xsl:element>
            <!-- repeat for the remainder of the original string-->
            <xsl:call-template name="csvtoxml">
                <xsl:with-param name="StringToTransform" select="substring-after($StringToTransform,',')" />
                <xsl:with-param name="ColumnNum" select="$ColumnNum + 1" />
            </xsl:call-template>
        </xsl:when>
        <!-- string does not contain newline, so just output it-->
        <xsl:otherwise>
            <xsl:element name="{concat('column', $ColumnNum)}">
                <xsl:value-of select="$StringToTransform" />
            </xsl:element>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
于 2012-08-17T22:19:05.067 に答える
1

この場合、XSLT を選択する理由がわかりません。これは、このような文字列処理操作の最初の選択肢ではありません。特に、ソース データが XML ではないため、ノードでラップして XML にするだけです。より明白なアプローチは、PHP などを介して CSV を処理することです。

いずれにせよ、質問に答えるために、EXSLT にアクセスできる場合 (これは PHP などの XSLT プロセッサで利用できることがよくあります):

ここで実行可能なデモ(出力ソースを参照)。

<!-- break into rows -->
<xsl:variable name='rows' select='str:split(root, "&#xA;")' />

<!-- root - kick things off -->
<xsl:template match='/'>
    <root>
        <xsl:apply-templates select='$rows' mode='row' />
    </root>
</xsl:template>

<!-- rows -->
<xsl:template match='token' mode='row'>
    <xsl:variable name='cols' select='str:split(., ",")' />
    <row>
        <xsl:apply-templates select='$cols' mode='col' />
    </row>
</xsl:template>

<!-- columns -->
<xsl:template match='token' mode='col'>
    <xsl:element name='col{position()}'>
        <xsl:value-of select='.' />
    </xsl:element>
</xsl:template>
于 2012-08-17T22:18:54.843 に答える