回答編集履歴

1

xpath 例

2020/06/21 19:38

投稿

KojiDoi
KojiDoi

スコア13671

test CHANGED
@@ -19,3 +19,193 @@
19
19
 
20
20
 
21
21
  こんな感じで実行して、問題なくxmlデータが出力されればいいのですが、掲出のデータではエラーメッセージが出るはずです。これをまず潰してください。
22
+
23
+
24
+
25
+ # xpathを検討してみる
26
+
27
+
28
+
29
+ 便宜上、中身を簡略化した次のようなテスト用データで考えてみます。
30
+
31
+
32
+
33
+ ```xml
34
+
35
+ <?xml version="1.0" encoding="UTF-8"?>
36
+
37
+ <!-- test200622a.xml -->
38
+
39
+ <BioSampleSet>
40
+
41
+ <BioSample> <!-- 理想を体現したノード -->
42
+
43
+ <Ids>
44
+
45
+ <Id>id1</Id>
46
+
47
+ </Ids>
48
+
49
+ <Attributes>
50
+
51
+ <Attribute attribute_name="strain">DOA9</Attribute>
52
+
53
+ <Attribute attribute_name="material">soil</Attribute>
54
+
55
+ </Attributes>
56
+
57
+ </BioSample>
58
+
59
+ <BioSample> <!-- idは上と同じだがmaterialがないノード -->
60
+
61
+ <Ids>
62
+
63
+ <Id>id1</Id>
64
+
65
+ </Ids>
66
+
67
+ <Attributes>
68
+
69
+ <Attribute attribute_name="strain">XXXX</Attribute>
70
+
71
+ </Attributes>
72
+
73
+ </BioSample>
74
+
75
+ <BioSample> <!-- idは上と違いmaterialがあるノード -->
76
+
77
+ <Ids>
78
+
79
+ <Id>id2</Id>
80
+
81
+ </Ids>
82
+
83
+ <Attributes>
84
+
85
+ <Attribute attribute_name="strain">YYYY</Attribute>
86
+
87
+ <Attribute attribute_name="material">soil</Attribute>
88
+
89
+ </Attributes>
90
+
91
+ </BioSample>
92
+
93
+ </BioSampleSet>
94
+
95
+ ```
96
+
97
+
98
+
99
+ 私の環境ではperlのXML::Pathモジュールに付随した`xpath`というツールが入っているのでこれを使いますが、xpathの書式はxmllintでも同じです。
100
+
101
+
102
+
103
+ ここではId="id1"なノードをまず探してみることにします。
104
+
105
+
106
+
107
+ ```
108
+
109
+ % xpath -e '//Id[text()="id1"]' test200622.xml
110
+
111
+ Found 2 nodes in test200622.xml:
112
+
113
+ -- NODE --
114
+
115
+ <Id>id1</Id>
116
+
117
+ -- NODE --
118
+
119
+ <Id>id1</Id>
120
+
121
+ ```
122
+
123
+ 次に、最終的にたどり着きたいノードAttributeと出発点のIdの位置関係を確認します。両ノードの共通祖先はBioSampleで、これはIdから見て2世代上になります。そこで、Idから二つ遡ったノードにアクセスするXpathを考えます。
124
+
125
+
126
+
127
+ ```
128
+
129
+ xpath -e '//Id[text()="id1"]/../..' test200622.xml [ ~/work ]
130
+
131
+ Found 2 nodes in test200622.xml:
132
+
133
+ -- NODE --
134
+
135
+ <BioSample> <!-- 理想を体現したノード -->
136
+
137
+ <Ids>
138
+
139
+ <Id>id1</Id>
140
+
141
+ </Ids>
142
+
143
+ <Attributes>
144
+
145
+ <Attribute attribute_name="strain">DOA9</Attribute>
146
+
147
+ <Attribute attribute_name="material">soil</Attribute>
148
+
149
+ </Attributes>
150
+
151
+ </BioSample>
152
+
153
+ -- NODE --
154
+
155
+ <BioSample> <!-- idは上と同じだがmaterialがないノード -->
156
+
157
+ <Ids>
158
+
159
+ <Id>id1</Id>
160
+
161
+ </Ids>
162
+
163
+ <Attributes>
164
+
165
+ <Attribute attribute_name="strain">XXXX</Attribute>
166
+
167
+ </Attributes>
168
+
169
+ </BioSample>
170
+
171
+ ```
172
+
173
+
174
+
175
+ さらにAttributeにおりていく記述を追加します。相手にするのは"material"なAttributeなので、制約条件を付けます。
176
+
177
+
178
+
179
+ ```
180
+
181
+ xpath -e '//Id[text()="id1"]/../..//Attribute[@attribute_name="material"]' test200622.xml [ ~/work ]
182
+
183
+ Found 1 nodes in test200622.xml:
184
+
185
+ -- NODE --
186
+
187
+ <Attribute attribute_name="material">soil</Attribute>
188
+
189
+ ```
190
+
191
+
192
+
193
+ タグの中身だけあればいいので、
194
+
195
+
196
+
197
+ ```
198
+
199
+ xpath -e '//Id[text()="id1"]/../..//Attribute[@attribute_name="material"]/text()' test200622.xml [ ~/work ]
200
+
201
+ Found 1 nodes in test200622.xml:
202
+
203
+ -- NODE --
204
+
205
+ soil
206
+
207
+ ```
208
+
209
+
210
+
211
+ 複数のIDについて処理し、なおかつIDと結果の対応がわかるように出力するためには、xpathの外で仕掛けを作る必要があるでしょう。