この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
そんなに難しくないよ
XML のパースと聞くと「複雑」や「難しい」などのイメージが強く、なかなか手が出しづらいと思っていませんか?
私も前はそうでした。
実は実際に手を動かしてみると簡単なんです。
今回は XML のパースについて、ライブラリを使わずに OS の組み込みクラスのみを用いたミニマムレベルのサンプルをご紹介します。
使用する XML は こちら。
a
と入力した時の Google Suggest の結果です。
この XML をパースして、サジェストの結果を表示してみましょう。
説明を簡略化するため通信は行わず、XML はテキストで保持しておくことにします。
iOS
iOS で XML をパースするためには NSXMLParser
クラスを使用します。
サンプルコード
@interface ViewController () <NSXMLParserDelegate>
@property (nonatomic, readonly) NSString *xmlString;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self parseXml];
}
- (void)parseXml
{
NSData *xmlData = [self.xmlString dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
parser.delegate = self;
[parser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"suggestion"]) {
NSString *keyword = attributeDict[@"data"];
NSLog(@"%@", keyword);
}
}
- (NSString *)xmlString
{
return @"\
<toplevel> \
<CompleteSuggestion> \
<suggestion data=\"amazon\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"american airlines\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"aol mail\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"aol\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"autozone\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"amazon prime\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"airbnb\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"apple\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"agario\"/> \
</CompleteSuggestion> \
<CompleteSuggestion> \
<suggestion data=\"american express\"/> \
</CompleteSuggestion> \
</toplevel>";
}
@end
実行結果
amazon
american airlines
aol mail
aol
autozone
amazon prime
airbnb
apple
agario
american express
解説
長いコードに見えますが、実際に XML に関する処理を行っているのは 10 行程度です。
長いのはデータの文字列です。
NSData *xmlData = [self.xmlString dataUsingEncoding:NSUTF8StringEncoding];
ここで文字列を NSData に変換しています。
NSXMLParser のイニシャライザに渡すためです。
適切なエンコーディングを設定しましょう。
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
parser.delegate = self;
NSXMLParser のインスタンスを生成し、デリゲートをこのクラスに設定しています。
[parser parse];
このコードでパース処理が実行され、適切なタイミングでデリゲートメソッドが呼ばれるようになります。
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"suggestion"]) {
NSString *keyword = attributeDict[@"data"];
NSLog(@"%@", keyword);
}
}
NSXMLParser クラスのデリゲートメソッドの 1 つです。
要素の開始タグが読み込まれた時に呼ばれます。
今回の例ですと、空要素 suggestion
の属性 data
の値が欲しいだけなので、このメソッド 1 つで事足ります。
ここでやっていることは、suggestion
の開始タグが読み込まれた時に data
属性の値を keyword という変数に代入し、ログ出力するというものです。
この程度の XML ならばこれだけの処理でパースできてしまいます。
簡単ですね。
Android
Android で XML をパースするためには XmlPullParser
クラスを使用します。
サンプルコード
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
parseXml();
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
}
private void parseXml() throws XmlPullParserException, IOException {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(new StringReader(xmlString()));
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("suggestion")) {
String keyword = parser.getAttributeValue(null, "data");
System.out.println(keyword);
}
}
eventType = parser.next();
}
}
private String xmlString() {
return ""
+ "<toplevel>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"amazon\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"american airlines\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"aol mail\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"aol\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"autozone\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"amazon prime\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"airbnb\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"apple\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"agario\"/>"
+ "</CompleteSuggestion>"
+ "<CompleteSuggestion>"
+ "<suggestion data=\"american express\"/>"
+ "</CompleteSuggestion>"
+ "<toplevel>";
}
}
実行結果
amazon
american airlines
aol mail
aol
autozone
amazon prime
airbnb
apple
agario
american express
解説
やっていることは iOS と同じです。
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
ファクトリクラスを利用して XmlPullParser のインスタンスを生成しています。
ここではファクトリに対して設定は行っていません。
parser.setInput(new StringReader(xmlString()));
パーサに対して XML データを渡しています。
int eventType = parser.getEventType();
getEventType()
でパースを開始しています。
開始時は START_DOCUMENT
という値が返ってきます。
while (eventType != XmlPullParser.END_DOCUMENT) {
// 省略
eventType = parser.next();
}
XML が全て読み込まれるまで、繰り返し次のイベントを取得していきます。
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("suggestion")) {
String keyword = parser.getAttributeValue(null, "data");
System.out.println(keyword);
}
}
開始タグが読み込まれた時、その要素名が suggestion
だった場合に data
属性の値を keyword という変数に代入し、ログ出力しています。
まとめ
- XML のパースは以下のクラスを使用すれば実現可能
- iOS: NSXMLParser
- Android : XmlPullParser
- ライブラリを使わずとも、短いコードで書くことができる
- そんなに難しくない
リンク
ミレニアム・ファルコン製作日記 #19
19 号 表紙
パーツ
成果
今回の作業は以下の 2 つでした。
- 穴メカのディテールアップ
- 通路チューブを組み立てる
穴メカ(あなめか) と読むのでしょうか?
どうやらこれはミレニアム・ファルコン専用の言葉のようです。
穴の中に見えるメカってことかな。
このパーツは船体底面に取り付けられます。
細かいパーツを 7 つほど接着しています。
映画の中では船体下部はあまり確認できないので、今回のようにじっくり観察できたのは楽しかったです。
相変わらず「こだわってるなぁ」と感じました。
はい来ました、アーチの作成。
内部の通路を組み立て、アーチを 3 つ取り付けました。
アーチの作成も一周回って楽しくなってきました。
それではまた次回。
May the Force be with you!