Groovy+Xml(その3:XmlSlurperとXmlParserの大きな違い)

2019-03-23Groovy

Groovy+Xml(その2:XmlSlurperで検索) で書いたのですが、 XmlSlurper を使用してXMLを操作すると、親ノードの指定に注意が必要でした。

デスクトップ上のjp_zipcode.xml

<Prefecture>
    <PrefectureName>XXX</PrefectureName>
    <City>
        <CityName>XXX</CityName>
        <Area>
            <AreaName>XXX</AreaName>
            ・・・
        </Area>
        <Area>
            <AreaName>XXX</AreaName>
            ・・・
        </Area>
    </City>
    <City>
        <CityName>XXX</CityName>
        <Area>
            <AreaName>XXX</AreaName>
            ・・・
        </Area>
    </City>
</Prefecture>
#!/usr/bin/env groovy
import static java.lang.System.*

final USER_HOME = new File(getProperty("user.home"))
final DESKTOP = new File("${USER_HOME}/デスクトップ")
def data = new XmlSlurper().parse(new File("${DESKTOP}/jp_zipcode.xml"))

def area = data.Prefecture.City.Area[0]

println area.AreaName
// City要素が全て取得されてしまう
println area."..".CityName

これがXPathの仕様なのかわからないですが、 親ノードを".."で指定した場合 、City要素が全て返却されてしまいます。

これを XmlParser を使用したコードに書き直してみました。

#!/usr/bin/env groovy
import static java.lang.System.*

final USER_HOME = new File(getProperty("user.home"))
final DESKTOP = new File("${USER_HOME}/デスクトップ")
def data = new XmlParser().parse(new File("${DESKTOP}/jp_zipcode.xml"))

def area = data.Prefecture.City.Area[0]

println area.AreaName.text()
// City要素はarea変数を内包している1ノードのみ取得できる
println area."..".CityName.text()

今度は".."で親ノードを指定した場合には1ノードのみ返却されました。

そのほかの部分にも注意が必要です。XmlSlurperでは ある要素ノード内のテキストノード は要素ノードのtoString()で出力可能のようです。
XmlParserでは ある要素ノード内のテキストノード はtext()メソッドを指定しないと正しく出力されません。

2019-03-23Groovy