2012-01-08 18 views
0

に基づいてノードセットから一つの要素を選択するために、鋸山でXPathを使用するためには、どのように、次のXMLを考えるとタグ名

<Container> 
<Set > 
<RecommendedCoverSong>Hurt by NiN - Johnny Cash</RecommendedCoverSong> 
<RecommendedOriginalSong>She Like Electric by Smoosh</RecommendedOriginalSong> 
<RecommendedDuetSong>Portland by Jack White and Loretta Lynn</RecommendedDuetSong> 
<RecommendedGroupSong>SoS by Abba</RecommendedGroupSong> 
<CoverSong>Kangaroo by Big Star - This Mortal Coil</CoverSong> 
<OriginalSong>Pick up the Change by Wilco</OriginalSong> 
<DuetSong>I am the Cosmos by Pete Yorn and Scarlett Johansen</DuetSong> 
<GroupSong>Kitties Never Rest by Rex or Regina</GroupSong> 
</Set> 
</Container> 

私は、タグの「カバー」が含まれる2つの要素をつかむしたいとそれぞれを操作します。

のXpathの鋸山の使用は簡単に最初のクエリ式そのようにできます:私はセットで(*使用して)すべての要素を選択して、XPath式の機能を使用しました

price_xml = doc_xml.xpath('Container/Set/*[contains(name(), "Cover")]')

には、大人が名前に含まれている必要があることを指定するために含まれています。これはノードセットに2つのNokogiri XMLノードを返します。

私がやりたかったことは、お気に入りのツールXpathを使って、タグのパターンに基づいてこれらの要素の1つを選択することでした。

しかし、私はノコギリを私に渡すことができませんでした。いくつかの解決策は、私が望む1要素以上の方法を選択することに終わりました。

node_xml.at_xpath('./self::*[not(contains(name(), "Recommended"))]') 
node_xml.at_xpath('./self::*[contains(name(), "Recommended")]') 

と繰り返し内の変数の代わりに定数を使用することを検討してください:

songtypes = ['Cover', 'Original', 'Duet', 'Group'] 
songtypes.each do |song| 

node_xml = doc.xpath('Container/Set/*[contains(name(), "Cover")]') 
#I wanted to be able to do the following 
# 
FavoriteCover = node_xml.xpath('./*[contains(name(), "Recommended")]') 
RegularCover = node_xml.xpath('./*[not(contains(name(), "Recommended"))]') 

#or 
FavoriteCover = node_xml.xpath('*[contains(name(), "Recommended")]') 
RegularCover = node_xml.xpath('*[not(contains(name(), "Recommended"))]') 
#But instead I had to resort to a Rails solution 

RegularCover = node_xml.find{ |node| node.name !~ /Recommended/ } 
FavoriteCover = node_xml.find{ |node| node.name =~ /Recommended/ } 

#Do something with the songs here 

end 

https://gist.github.com/1579343

答えて

1

のようなものを試してみてください(ノードセット内のノードはまだ両親との関係が含まれているため)。

それとも、ノード名を生成することができます

songtypes = ['Cover', 'Original', 'Duet', 'Group'] 
songtypes.each do |st| 
    regular = doc.at_xpath("Container/Set/#{st}Song") 
    recommended = doc.at_xpath("Container/Set/Recommended#{st}Song") 
end 
+0

二つのフォローアップの質問: 1)定数対変数については?タイプハッシュを指していますか? songtypes = ['Cover'、 'Original'、 'Duet'、 'Group'] 2)私は「self ::」というものに関するドキュメントを見つけることはできませんが、それは素晴らしいものです。それはXpath 2.0だけですか? –

+0

1)私はあなたが反復の中で使った定数 'FavoriteCover'と' RegularCover'について話しています。 2)これはhttp://www.w3.org/TR/xpath/で説明されている1.0の機能です – taro

関連する問題