使用XmlSlurper:選択方法のサブ要素を繰り返し処理を行は、GPathResult
-
16-09-2019 - |
質問
皆様にお伝えしたくて書き込み、HTMLパーサを使用するTagSoup渡の形構造XMLSlurper.
この節のコード:
def htmlText = """
<html>
<body>
<div id="divId" class="divclass">
<h2>Heading 2</h2>
<ol>
<li><h3><a class="box" href="#href1">href1 link text</a> <span>extra stuff</span></h3><address>Here is the address<span>Telephone number: <strong>telephone</strong></span></address></li>
<li><h3><a class="box" href="#href2">href2 link text</a> <span>extra stuff</span></h3><address>Here is another address<span>Another telephone: <strong>0845 1111111</strong></span></address></li>
</ol>
</div>
</body>
</html>
"""
def html = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser()).parseText( htmlText );
html.'**'.grep { it.@class == 'divclass' }.ol.li.each { linkItem ->
def link = linkItem.h3.a.@href
def address = linkItem.address.text()
println "$link: $address\n"
}
私は期待されるようそれぞれ選択し'li'にその取得が可能な対応するhrefおよび住所ます。代わりに、私はこの出力です:
#href1#href2: Here is the addressTelephone number: telephoneHere is another addressAnother telephone: 0845 1111111
私は次の各例は、ウェブおよびこれらのいずれかの対応を含みつつあるとライナーにとっての"すべてを取得のリンクからこのファイル".このようにit.h3.a.@href 表現の収集をすべてhrefの文字来に仕上がってしまいました広い範囲にわたって参考に親li'ノードです。
きん:
- 理由はいろんの出力を示し
- かを取得することができ、[url/アドレスのペアごとliの"ゆるっと"したアイテム
感謝。
解決
のfindとgrepのを置き換えます:
html.'**'.find { it.@class == 'divclass' }.ol.li.each { linkItem ->
def link = linkItem.h3.a.@href
def address = linkItem.address.text()
println "$link: $address\n"
}
あなたが得られます。
#href1: Here is the addressTelephone number: telephone
#href2: Here is another addressAnother telephone: 0845 1111111
はgrepはArrayListのを返しますが、戻りNodeChildクラスを見つけます:
println html.'**'.grep { it.@class == 'divclass' }.getClass()
println html.'**'.find { it.@class == 'divclass' }.getClass()
での結果ます:
class java.util.ArrayList
class groovy.util.slurpersupport.NodeChild
これはあなたができたのgrepを使用したい場合は、その後巣別のこのような各それが機能するためには、
html.'**'.grep { it.@class == 'divclass' }.ol.li.each {
it.each { linkItem ->
def link = linkItem.h3.a.@href
def address = linkItem.address.text()
println "$link: $address\n"
}
}
かいつまんで、あなたのケースでは、かなりのgrepよりも見つける使用します。
他のヒント
このトリッキーな一つです。クラス=「divclass」がただ一つの要素がある場合、前の答えは確か結構です。グレップから複数の結果があった場合には、単一の結果を見つけるには、()の答えではありません。結果はArrayListのあることを指摘することは正しいです。外側の入れ子になった.each()ループを挿入するクロージャパラメータにGPathResult DIV を提供します。ここからドリルダウンが期待される結果を続行することができます。
html."**".grep { it.@class == 'divclass' }.each { div -> div.ol.li.each { linkItem ->
def link = linkItem.h3.a.@href
def address = linkItem.address.text()
println "$link: $address\n"
}}
元のコードの動作は、同様に、説明の少しを使用することができます。プロパティはGroovyで一覧にアクセスしたときは、リスト内の各要素のプロパティを持つ新しいリスト(同じサイズ)を取得します。グレップで見つかったリストは、()だけで1つのエントリがあります。その後、我々は素晴らしいですプロパティのオールのための一つのエントリを取得します。次はそのエントリのol.itの結果を得ます。それは()== 1再びサイズのリストですが、サイズのエントリで、この時間は()== 2.私たちは、そこに外側のループを適用し、同じ結果を得ることができ、我々がしたい場合:
html."**".grep { it.@class == 'divclass' }.ol.li.each { it.each { linkItem ->
def link = linkItem.h3.a.@href
def address = linkItem.address
println "$link: $address\n"
}}
は、複数のノードを表す任意のGPathResultでは、我々はすべてのテキストの連結を取得します。それは、その後、の。
対処するために、最初のの@href のために、オリジナルの結果であり、私は以前の回答を使用したバージョンのため、書き込み時にはすべて正しいと信じています。しかし、私はGroovyの2.3.7と0.7.1 HTTPBuilderとGrails 2.4.4を使用していますが、大きな問題があります - の HTML要素が大文字に変換されているのそれはNekoHTMLにボンネットの下で使用により、これは表示されます。 :
http://nekohtml.sourceforge.net/faq.html#uppercaseする
このため、受け入れ答えで解決策をとして記述する必要があります
html.'**'.find { it.@class == 'divclass' }.OL.LI.each { linkItem ->
def link = linkItem.H3.A.@href
def address = linkItem.ADDRESS.text()
println "$link: $address\n"
}
これは、デバッグに非常にイライラさせられた、それは誰かに役立ちます願っています。