回答編集履歴

3

テキスト修正

2018/01/04 18:51

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -114,7 +114,9 @@
114
114
 
115
115
 
116
116
 
117
+ 以下のような別解を考えました。
118
+
117
- 質問で問われている本題から離れてしまいますが、次のような別解を考えました。
119
+ (ただし、質問で問われている本題から離れてしまうと思うので、あくまで参考に留めて頂ければと思います
118
120
 
119
121
 
120
122
 
@@ -270,13 +272,13 @@
270
272
 
271
273
 
272
274
 
273
- 上記のコードで、`Hash#to_xml` を再帰メソッドとして実装しているので
275
+ 上記のコードで、`Hash#to_xml` を再帰メソッドとして実装しているので
274
-
276
+
275
-  「結局手間としては同じでは?」とお思いになるかもしれませんが、
277
+ 「結局手間としては同じでは?」とお思いになるかもしれませんが、
276
-
278
+
277
-  ハッシュをXMLにするメソッドも自分で書かなくても、
279
+ ハッシュをXMLにするメソッドも自分で書かなくても、
278
-
280
+
279
-  以下のようなgemがあります。
281
+ 以下のようなgemがあります。
280
282
 
281
283
 
282
284
 
@@ -288,4 +290,14 @@
288
290
 
289
291
 
290
292
 
293
+ この別解で、何が言いたいかと言えば、与件を
294
+
295
+ 「XMLのテキストノードへのパスを取得する」問題と置き換えれば、
296
+
297
+ 自分で再帰メソッドを書く手間をかけなくても欲しい情報が得られるのでは?
298
+
299
+ ということでした。
300
+
301
+
302
+
291
303
  ご参考になれば幸いです。

2

テキスト修正

2018/01/04 18:51

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -270,4 +270,22 @@
270
270
 
271
271
 
272
272
 
273
+ ※上記のコードで、`Hash#to_xml` を再帰メソッドとして実装しているので
274
+
275
+  「結局手間としては同じでは?」とお思いになるかもしれませんが、
276
+
277
+  ハッシュをXMLにするメソッドも自分で書かなくても、
278
+
279
+  以下のようなgemがあります。
280
+
281
+
282
+
283
+ - ActiveSupport::[CoreExtensions::Array::Conversions#to_xml](http://api.rubyonrails.org/v2.3/classes/ActiveSupport/CoreExtensions/Array/Conversions.html#M000784)
284
+
285
+
286
+
287
+ - [Gyoku](https://github.com/savonrb/gyoku)
288
+
289
+
290
+
273
291
  ご参考になれば幸いです。

1

別解追加

2018/01/04 18:42

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -105,3 +105,169 @@
105
105
 
106
106
 
107
107
  参考になりましたら幸いです。
108
+
109
+
110
+
111
+ ----
112
+
113
+ **追記**
114
+
115
+
116
+
117
+ 質問で問われている本題から離れてしまいますが、次のような別解を考えました。
118
+
119
+
120
+
121
+ 所与のハッシュ`sample_hash`は、構造的に次のXMLと等価です。
122
+
123
+ ```xml
124
+
125
+ <?xml version="1.0" encoding="UTF-8"?>
126
+
127
+ <root>
128
+
129
+ <nest1-1>value1-1</nest1-1>
130
+
131
+ <nest1-2>
132
+
133
+ <nest2-1>
134
+
135
+ <nest3-1a>26513</nest3-1a>
136
+
137
+ <nest3-1b>3</nest3-1b>
138
+
139
+ </nest2-1>
140
+
141
+ <nest2-2>
142
+
143
+ <nest3-2a>317829</nest3-2a>
144
+
145
+ <nest3-2b>50</nest3-2b>
146
+
147
+ </nest2-2>
148
+
149
+ </nest1-2>
150
+
151
+ </root>
152
+
153
+ ```
154
+
155
+ ただしXMLにするためには、最上位のノードは1つなので、上記では
156
+
157
+ 便宜的に `<root>` 要素をトップに追加しています。
158
+
159
+
160
+
161
+ XMLを扱う問題に置き換えれば、`value1-1` や `26513`は XMLのテキストノードで、
162
+
163
+ これらはXPath で `//text()` という指定でまとめて取得できます。
164
+
165
+ あとは、テキストノードのそれぞれについて、XPathを逆に求めれば、
166
+
167
+ テキストノードとそれに至るXPathの組を得ることができます。
168
+
169
+
170
+
171
+ この考えで作成したスクリプトが以下です。
172
+
173
+
174
+
175
+ ```ruby
176
+
177
+ # coding: utf-8
178
+
179
+
180
+
181
+ require 'nokogiri'
182
+
183
+
184
+
185
+ sample_hash =
186
+
187
+ {'nest1-1' => 'value1-1',
188
+
189
+ 'nest1-2' =>
190
+
191
+ {
192
+
193
+ 'nest2-1' => {
194
+
195
+ 'nest3-1a' => '26513',
196
+
197
+ 'nest3-1b' => '3'
198
+
199
+ },
200
+
201
+ 'nest2-2' => {
202
+
203
+ 'nest3-2a' => '317829',
204
+
205
+ 'nest3-2b' => '50'
206
+
207
+ }
208
+
209
+ }
210
+
211
+ }
212
+
213
+
214
+
215
+ class Hash
216
+
217
+ def to_xml
218
+
219
+ map do |k, v|
220
+
221
+ text = Hash === v ? v.to_xml : v
222
+
223
+ '<%s>%s</%s>' % [k, text, k]
224
+
225
+ end.join
226
+
227
+ end
228
+
229
+ end
230
+
231
+
232
+
233
+ xml ='<?xml version="1.0" encoding="UTF-8"?><root>%s</root>' % [sample_hash.to_xml]
234
+
235
+
236
+
237
+ Nokogiri::XML(xml).xpath('//text()').each do |item|
238
+
239
+ xpath = Nokogiri::CSS.xpath_for item.css_path
240
+
241
+ puts '%s=%s' % [xpath[0], item]
242
+
243
+ end
244
+
245
+ ```
246
+
247
+ 上記では、XMLをパース(解析)するために、`nokogiri` を使っており、
248
+
249
+ このスクリプトを実行すると以下が表示されます。
250
+
251
+
252
+
253
+ > //root/nest1-1/child::text()=value1-1
254
+
255
+ //root/nest1-2/nest2-1/nest3-1a/child::text()=26513
256
+
257
+ //root/nest1-2/nest2-1/nest3-1b/child::text()=3
258
+
259
+ //root/nest1-2/nest2-2/nest3-2a/child::text()=317829
260
+
261
+ //root/nest1-2/nest2-2/nest3-2b/child::text()=50
262
+
263
+
264
+
265
+ このように与題をXMLのテキストノードの走査と考えて、`//text()` でテキストノードをまとめて
266
+
267
+ 取ってこれるパーサーを使えば、自分で再帰的にテキストノードを探すメソッドを作らなくても
268
+
269
+ よくなります。
270
+
271
+
272
+
273
+ ご参考になれば幸いです。