XMLファイルの扱い

RubyMotion では、ライブラリを読み込めないので rexml を動かすには面倒なことをしないといけないようなので、NSXMLDocument と NSXMLParser を使ってみたメモ。

NSXMLDocument で、XML ファイルを読み込むには、initWithContentsOfURL:options:error: を使う。ここでは、path から NSURL オブジェクトを作って利用している。NSXMLDocumentTidyXML を指定すると、フォーマットがちゃんとしていない XML ファイルをちゃんとした XML に直してから読み込んでくれる。

xmlDoc = NSXMLDocument.alloc.initWithContentsOfURL(NSURL.fileURLWithPath(path),options:NSXMLDocumentTidyXML,error:nil)

このほかにも、initWithXMLString:options:error: で、XML の文字列から作ることできる。たとえば、テキストファイルを読み込んで、なんらかの処理をした上で XML フォーマットにして読み込むとかできる。

読み込んだ NSXMLDocument から、rootElement で、ルート要素の NSXMLElement オブジェクトが取り出せる。

rootElement = xmlDoc.rootElement

NSXMLElement は NSXMLNode を継承しているので、name で要素名が、stringValue で子ノードのテキストが取り出せる。XMLString では、XML タグを保持したままのテキストが得られ、XMLStringWithOptions でオプションを指定して XML テキストが得られる。たとえば、NSXMLNodePrettyPrint をオプションに指定すると、XML として見やすく成形されたテキストとして得られる。

elementName = rootElement.name

text = rootElement.stringValue

ただ、どうやら whitespace のみのノードのテキストは無視されるようなので、うまくいく方法がないかと思ってる。

これら以外に、children で子ノードの配列が、childCount で子ノードの数が、parent で親ノードが得られる。

rootElement.children

rootElement.childCount

rootElement.parent

これで順にノードをたどっていくこともできるが、XPath がわかっていれば、nodesForXPath:error: で直接そのノードにアクセスできる。この場合は、同じ XPath の要素を配列として取り出すことができる。

nodes = rootElement.nodesForXPath(xpath,error:nil)

次に、NSXMLParser を使った場合のメモ。

XML ファイルからは、initWithContentsOfURL で NSXMLParser オブジェクトを作る。NSXMLParser は、setDelegate で delegate を指定して、parse で処理を開始する。

parser = NSXMLParser.alloc.initWithContentsOfURL(NSURL.fileURLWithPath(path))

parser.setDelegate(self)

parser.parse

ここでの処理は delegate のメソッドを用意して、そこで情報を捕まえる。

def parserDidStartDocument(parser)

# ここに、書類ごとにパースを実行した時点の処理を入れる。

end

def parserDidEndDocument(parser)

# ここには、書類ごとにパースの実行を終えた時点の処理を入れる。

end

def parser(parser,didStartElement:elementName,namespaceURI:uri,qualifiedName:name,attributes:attributes)

# ここには、スタートタグが見つかった時の処理を入れる。

# elementName に要素名が入り、attributes には、属性の情報が NSDictionary/Hash で入る。

end

def parser(parser,didEndElement:elementName,namespaceURI:uri,qualifiedName:name)

# ここには、エンドタグが見つかった時の処理を入れる。

# elementName に要素名が入る。

end