2012-01-17 35 views
4

NokogiriとXPathを使用してXMLを解析しています。私がこれをするとき:子要素のみを選択するXPath(空白のテキストノードではない)

すべてのノードを出力しますが、名前の間にも 'text'が表示されます。私はなぜ知っていると思う:私のXMLで

、このようなノード間のスペースがあります:"<a1>hi</a1> \n <a2>bye</a2>"

は、私は、ノード間のものを無視して、それを伝えることができる方法はありますか?

+2

」の非要素(テキスト)の子要素がありますか?任意のコメントノード? (将来、XMLの実際のテストサンプルを提供し、あなたが望む結果を得ることはより良い結果を得るのに役立ちます) – Phrogz

+0

*要素*の間のテキスト(空白を含む)も*ノード*です。見つけたいものは単純な要素です。 –

答えて

7

使用

//Order/node()[not(self::text()[not(normalize-space())])] 

これは、ホワイトスペースを完全に成るテキストノードであるものを除き、いかなるOrder要素のすべての子ノードを選択します。

XSLT - ベースの検証

この変換は、以下のXML文書に適用され
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 


<xsl:template match="/*"> 
    <xsl:variable name="vSel1" select="//Order/node()"/> 
    <xsl:variable name="vSel2" select= 
    "//Order/node()[not(self::text()[not(normalize-space())])]"/> 

    <xsl:for-each select="$vSel1"> 
     <xsl:value-of select="concat('&#xA;',position(), ': ')"/> 
     <xsl:copy-of select="."/> 
     <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
================ 
    <xsl:for-each select="$vSel2"> 
     <xsl:value-of select="concat('&#xA;',position(), ': ')"/> 
     <xsl:copy-of select="."/> 
     <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

<t> 
<Order> 
    <a/> 
    <b>xxx</b> 
    <c/> 
</Order> 
<Order> 
    <d/> 
    <e>xxx</e> 
    <f/> 
</Order> 
</t> 

2つのXPath式が評価され、2つのノード選択されたノードの対応するセットが出力され、その各々は位置番号

1: 


2: <a/> 

3: 


4: <b>xxx</b> 

5: 


6: <c/> 

7: 


8: 


9: <d/> 

10: 


11: <e>xxx</e> 

12: 


13: <f/> 

14: 


================ 

1: <a/> 

2: <b>xxx</b> 

3: <c/> 

4: <d/> 

5: <e>xxx</e> 

6: <f/> 
4

あなただけの要素が必要な場合は、より良いXPathを使用します。/*を求めるあなたに要素すべての子を見つける:

また
require 'nokogiri' 
doc = Nokogiri.XML("<r><a>1</a>\n\t<b>2</b></r>") 
p doc.xpath('/r/child::node()').map(&:name) 
#=> ["a", "text", "b"] 

p doc.xpath('/r/*').map(&:name) 
#=> ["a", "b"] 

を、あなたは、任意のテキストノートを捨てて鋸山を依頼することができます空白のみ:

doc2 = Nokogiri.XML("<r><a>1</a>\n\t<b>2</b></r>",&:noblanks) 
p doc2.xpath('/r/child::node()').map(&:name) 
#=> ["a", "b"] 

それとも、あなたはさらに、任意の基準に基づいて、あなたのノードセットをフィルタリングするためのRubyを使用することができます。

mine = doc.xpath('/r/child::node()').select do |node| 
    node.type != Nokogiri::XML::Node::TEXT_NODE || node.content =~ /\S/ 
end 
p mine.map(&:name) 
#=> ["a", "b"] 
関連する問題