challenge 固定長データ

固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。

ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。

  1. 姓 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  2. 名 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  3. 性別 (F,M,Uの3種類、1文字)
  4. 年齢 (3桁の数字、桁数が足りない場合は、ゼロで埋めず、頭を空白で埋めてあります。
  5. 年 2008 固定
  6. 月 03 固定
  7. さらに以下のデータが日付分くりかえされます。
    1. 日付 (01 〜 31) 2文字
    2. 朝食のメニュー (500文字)
    3. 昼食のメニュー (500文字)
    4. 夕食のメニュー (500文字)

以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。

この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。

Posted feedbacks - XSLT

単純にデータを読み込んで、XML 形式に転写する
だけですぅ。 こんな簡単なことするだけでも XSLT 
だとこんなに長くなるんだろか? XSLT 初心者の
僕にはわかんないやぁ~

データは XML ファイルで与えます。ルートノードの
直下に 文字列を書きます。ルートノードの名前 は
SerializedRecords にする。

そそ、Array っていうオブジェクトを (仮想的に) 定
義しました。 Array_push 関数 (ほんとはテンプ
レート) で データ追加するだけ。これ定義するだけ
でも行数つかったぁ。。。

もっとエレガントなやり方あんのかもしれない。
だれか教えて~
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- ==========================================================================
定数の設定
=========================================================================== -->

<xsl:variable name="姓_length" select="12" />
<xsl:variable name="名_length" select="12" />
<xsl:variable name="性別_length" select="1" />
<xsl:variable name="年齢_length" select="3" />
<xsl:variable name="年_length" select="4" />
<xsl:variable name="月_length" select="2" />
<xsl:variable name="日付_length" select="2" />
<xsl:variable name="朝食のメニュー_length" select="500" />
<xsl:variable name="昼食のメニュー_length" select="500" />
<xsl:variable name="夕食のメニュー_length" select="500" />


<xsl:variable name="姓_offset" select="1" />
<xsl:variable name="名_offset" select="$姓_offset + $姓_length" />
<xsl:variable name="性別_offset" select="$名_offset + $名_length" />
<xsl:variable name="年齢_offset" select="$性別_offset + $性別_length" />
<xsl:variable name="年_offset" select="$年齢_offset + $年齢_length" />
<xsl:variable name="月_offset" select="$年_offset + $年_length" />
<xsl:variable name="ヘッダー_length" select="$姓_length + $名_length + $性別_length + $年齢_length + $年_length + $月_length" />

<xsl:variable name="日付_offset" select="1" />
<xsl:variable name="朝食のメニュー_offset" select="$日付_offset + $日付_length" />
<xsl:variable name="昼食のメニュー_offset" select="$朝食のメニュー_offset + $朝食のメニュー_length" />
<xsl:variable name="夕食のメニュー_offset" select="$昼食のメニュー_offset + $昼食のメニュー_length" />
<xsl:variable name="一日のメニュー_length" select="$日付_length + $朝食のメニュー_length + $昼食のメニュー_length + $夕食のメニュー_length" />



<!-- ==========================================================================
メインルーチン
=========================================================================== -->

<xsl:template match="/">
  <xsl:call-template name="stringToRecords">
    <xsl:with-param name="string" select="/SerializedRecords/text ()" />
    <xsl:with-param name="人数" select="500" />
  </xsl:call-template>
</xsl:template>



<!-- ==========================================================================
Array オブジェクトの定義
(タグの名前はなんでも良かったので HTML にある ol と li にした)
=========================================================================== -->

<xsl:template name="new_Array">
  <ol />
</xsl:template>

<xsl:template name="Array_push">
  <xsl:param name="array" />
  <xsl:param name="element" />

  <ol>
    <xsl:for-each select="$array/ol/li">
      <xsl:copy-of select="." />
    </xsl:for-each>
    <li><xsl:copy-of select="$element" /></li>
  </ol>
</xsl:template>



<!-- ==========================================================================
stringToRecords: レコードデータの読み込み
人数 分だけ レコード を読み込みだけ。ただし、メニューのところは別関数で...
=========================================================================== -->

<xsl:template name="stringToRecords">
  <xsl:param name="string" />
  <xsl:param name="人数" />

  <xsl:call-template name="stringToRecords_">
    <xsl:with-param name="string" select="$string" />
    <xsl:with-param name="records">
      <xsl:call-template name="new_Array" />
    </xsl:with-param>
    <xsl:with-param name="人数" select="$人数" />
  </xsl:call-template>
</xsl:template>

<xsl:template name="stringToRecords_">
  <xsl:param name="string" />
  <xsl:param name="records" />
  <xsl:param name="人数" />

  <xsl:choose>
    <xsl:when test="$人数 = 0">
      <xsl:copy-of select="$records" />
    </xsl:when>

    <xsl:otherwise>
      <!-- 日数 は本来ならその月にあわせて変化させるんだろぉなぁ -->
      <xsl:variable name="日数" select="31" />

      <!-- タグの名前は何でも良かったので HTML の table 形式にした。 -->
      <xsl:variable name="record">
        <table><tbody>
          <tr><td>姓</td><td><xsl:value-of select="substring ($string, $姓_offset, $姓_length)" /></td></tr>
          <tr><td>名</td><td><xsl:value-of select="substring ($string, $名_offset, $名_length)" /></td></tr>
          <tr><td>性別</td><td><xsl:value-of select="substring ($string, $性別_offset, $性別_length)" /></td></tr>
          <tr><td>年齢</td><td><xsl:value-of select="substring ($string, $年齢_offset, $年齢_length)" /></td></tr>
          <tr><td>年</td><td><xsl:value-of select="substring ($string, $年_offset, $年_length)" /></td></tr>
          <tr><td>月</td><td><xsl:value-of select="substring ($string, $月_offset, $月_length)" /></td></tr>
          <tr><td>各日のメニュー</td>
            <td>
            <xsl:call-template name="stringToMenues">
              <xsl:with-param name="string" select="substring ($string, $ヘッダー_length + 1)" />
              <xsl:with-param name="日数" select="$日数" />
            </xsl:call-template>
            </td>
          </tr>
        </tbody></table>
      </xsl:variable>

     <!-- これまで読み込んだデータ $records に 今読み込んだデータ $record を 追加~ -->
      <xsl:variable name="records_">
        <xsl:call-template name="Array_push">
          <xsl:with-param name="array" select="$records" />
          <xsl:with-param name="element" select="$record" />
        </xsl:call-template>
      </xsl:variable>

      <!-- 人数分だけ再帰~。もちろんこれまでのデータ $records_ も渡す... -->
      <xsl:call-template name="stringToRecords_">
        <xsl:with-param name="string" select="substring ($string, $ヘッダー_length + $日数 * $一日のメニュー_length + 1)" />
        <xsl:with-param name="records" select="$records_" />
        <xsl:with-param name="人数" select="$人数 - 1" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>



<!-- ==========================================================================
stringToMenues: 一日のメニューの読み込み
固定長のものを 日数 回数 単純に 繰り返し読み込むだけ...
=========================================================================== -->

<xsl:template name="stringToMenues">
  <xsl:param name="string" />
  <xsl:param name="日数" />

  <xsl:call-template name="stringToMenues_">
    <xsl:with-param name="string" select="$string" />
    <xsl:with-param name="日数" select="$日数" />
    <xsl:with-param name="menues">
      <xsl:call-template name="new_Array" />
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

<xsl:template name="stringToMenues_">
  <xsl:param name="string" />
  <xsl:param name="日数" />
  <xsl:param name="menues" />

  <xsl:choose>
    <xsl:when test="$日数 = 0">
      <xsl:copy-of select="$menues" />
    </xsl:when>

    <xsl:otherwise>
      <!-- タグの名前は何でも良かったので HTML の table 形式にした。 -->
      <xsl:variable name="menu">
        <table><tbody>
          <tr><td>日付</td><td><xsl:value-of select="substring ($string, $日付_offset, $日付_length)" /></td></tr>
          <tr><td>朝食のメニュー</td><td><xsl:value-of select="substring ($string, $朝食のメニュー_offset, $朝食のメニュー_length)" /></td></tr>
          <tr><td>昼食のメニュー</td><td><xsl:value-of select="substring ($string, $昼食のメニュー_offset, $昼食のメニュー_length)" /></td></tr>
          <tr><td>夕食のメニュー</td><td><xsl:value-of select="substring ($string, $夕食のメニュー_offset, $夕食のメニュー_length)" /></td></tr>
        </tbody></table>
      </xsl:variable>

     <!-- これまで読み込んだデータ $menues に 今読み込んだデータ $menu を 追加~ -->
      <xsl:variable name="menues_">
        <xsl:call-template name="Array_push">
          <xsl:with-param name="array" select="$menues" />
          <xsl:with-param name="element" select="$menu" />
        </xsl:call-template>
      </xsl:variable>

     <!-- 日数分だけ再帰~。もちろんこれまでのデータ $menues_ も渡す... -->
     <xsl:call-template name="stringToMenues_">
        <xsl:with-param name="string" select="substring ($string, $一日のメニュー_length + 1)" />
        <xsl:with-param name="日数" select="$日数 - 1" />
        <xsl:with-param name="menues" select="$menues_" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Index

Feed

Other

Link

Pathtraq

loading...