2011-02-03 37 views
1

Nokogiriを使用しているいくつかの要素を除いて、特定のノード以下のタグをすべて削除するにはどうすればよいですか?たとえば、この設定を を使用して:Nokogiriを使用しているもの以外のすべてのタグを削除する方法

src = <<EOS 
<html> 
    <body> 
    <p> 
     Hello <i>world</i>! 
     This is <em>another</em> line. 
     <p><h3>And a paragraph <em>with</em> a heading.</h3></p> 
     <b>Third line.</b> 
    </p> 
    </body> 
</html> 
EOS 

doc = Nokogiri::HTML(src)  
para = doc.at('//p') 

(その内容を維持しながら)私は<I>と<B>要素を除いて、段落内のすべての要素を削除するにはどうすればよいですか? だから、結果は次のようになります。

あなたのサンプルに適用さ
<html> 
    <body> 
    <p> 
     Hello <i>world</i>! 
     This is another line. 
     And a paragraph with a heading. 
     <b>Third line.</b> 
    </p> 
    </body> 
</html> 
+1

これは、適切なXSLTタスクによく似ています。 – Flack

+0

NokogiriはXSLTもサポートしているので、XSLTの例がそうです。 – Erik

+0

私は、私の答えを確認してください。 – Flack

答えて

0
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="yes"/> 

    <xsl:template match="node() | @*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node() | @*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="em | p/p | h3"> 
     <xsl:apply-templates/> 
    </xsl:template> 
</xsl:stylesheet> 

、結果は以下のようになります。コメントで要求されるように

<html> 
    <body> 
     <p> 
     Hello 
      <i>world</i>! 
     This is another line. 
     And a paragraph with a heading. 
      <b>Third line.</b> 
     </p> 
    </body> 
</html> 

EDIT。

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="yes"/> 

    <xsl:template match="node() | @*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node() | @*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="p//*[not(self::i or self::b)]"> 
     <xsl:apply-templates/> 
    </xsl:template> 
</xsl:stylesheet> 

これはib要素を除いて、p内のすべての要素(マークアップではなく、文字列値)を削除します。ここでは、

<?xml version="1.0"?> 
<html> 
    <body> 
    <p> 
     Hello <i>world</i>! 
     This is another line. 
     And a paragraph with a heading. 
     <b>Third line.</b> 
    </p> 
    </body> 
</html> 
+0

私はそれを試しました。この具体例では動作します。しかし、私はいくつかを除いてすべての**タグを削除する方法を探しています。これは私の例からem、p/p、h3を削除するだけです。どのようにこれを達成するためのアイデア?私はXSLTに慣れていません(私は* [not(name()= 'i')] [not(name()= 'b')]のようなものを試しましたが、意図した結果は得られません) – Erik

+0

@Erik 。私は答えを編集しました。 – Flack

+1

NokogiriをXSLTで使用する方法を示す必要があります。より高度なノコギリ(Nokogiri)ユーザーはそれを理解することができますが、それはSOのことではありません。 –

3

フラックは、私がここにフル鋸山ベースの例を提供XSLTテンプレートを使用して正しい答えを与えましたXSLTなし:

require 'nokogiri' 

src = <<EOS 
<html> 
    <body> 
    <p> 
     Hello <i>world</i>! 
     This is <em>another</em> line. 
     <p><h3>And a paragraph <em>with</em> a heading.</h3></p> 
     <b>Third line.</b> 
    </p> 
    </body> 
</html> 
EOS 

doc = Nokogiri::HTML(src) 

if (doc.errors.any?) 
    puts "doc.errors:" 
    doc.errors.each do |e| 
    puts "#{ e.line }: #{ e.to_s }" 
    end 
    puts 
end 

doc.search('//p/*').each do |n| 
    n.replace(n.content) unless (%w[i b].include?(n.name)) 
end 

puts doc.to_html 
# >> doc.errors: 
# >> 6: Unexpected end tag : p 
# >> 8: Unexpected end tag : p 
# >> 
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
# >> <html><body> 
# >>  <p> 
# >>  Hello <i>world</i>! 
# >>  This is another line. 
# >>  </p> 
# >> <p></p> 
# >> <h3>And a paragraph <em>with</em> a heading.</h3> 
# >>  <b>Third line.</b> 
# >>  
# >> </body></html> 

ノコギリはマークアップに満足していないし、som eの修正。タグを取り除く実際のコードは3行で、1行に書かれている可能性があります。

+0

生成された出力を追加してください。 –

+0

確かに、私はそれを追加しました。 – Erik

4

だけ例を仕上げるために鋸山を使用して一つだ:

xslt = <<EOS 
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"> 
    <output method="html" indent="yes"/> 

    <template match="node() | @*"> 
     <copy> 
      <apply-templates select="node() | @*"/> 
     </copy> 
    </template> 

    <template match="p//*[not(self::i or self::b)]"> 
     <apply-templates/> 
    </template> 
</stylesheet> 
EOS 

src = <<EOS 
<html> 
    <body> 
    <p> 
     Hello <i>world</i>! 
     This is <em>another</em> line. 
     <p><h3>And a paragraph <em>with</em> a heading.</h3></p> 
     <b>Third line.</b> 
    </p> 
    </body> 
</html> 
EOS 

doc  = Nokogiri::XML(src) 
paragraph = doc.at('p') 

xslt = Nokogiri::XSLT(xslt) 
transformed_paragraph = xslt.transform(paragraph) 
paragraph.replace transformed_paragraph.children 

puts doc 

出力:

+1

XPathバリエーション: 'doc.xpath( '// p/* [NULL](name()=" i "またはname()=" b "))')' – Phrogz

+0

XPath式は直接の子を選択するだけですが、要素は(X)HTMLの古典的なコンテンツです...再帰では、複雑さとXSLT答えの理由があります。 –

関連する問題