どのように私は鋸山は、XML文書を解析して返すために得ることができますか?

StackOverflow https://stackoverflow.com/questions/1157138

質問

ここではいくつかの奇数判定のサンプルです:

#!/usr/bin/ruby

require 'rubygems'
require 'open-uri'
require 'nokogiri'

print "without read: ", Nokogiri(open('http://weblog.rubyonrails.org/')).class, "\n"
print "with read:    ", Nokogiri(open('http://weblog.rubyonrails.org/').read).class, "\n"

このリターンを実行します:

without read: Nokogiri::XML::Document
with read:    Nokogiri::HTML::Document

readなしのXMLを返し、それをHTMLのですか?

:最初に、私は鋸山ストリームからOpenURIの「コンテンツタイプ」を読んでされていなければならないと思ったが、それは'text/html'を返すように、ウェブページは、「過渡的なXHTML」として定義されています
(rdb:1) doc = open(('http://weblog.rubyonrails.org/'))
(rdb:1) doc.content_type
"text/html"

どのサーバが返しているものです。だから、今私は、鋸山は、2つの異なる値を返している原因を把握しようとしています。これは、テキストを解析し、コンテンツがHTMLまたはXMLであるかどうかを判断するヒューリスティックを使用しているように表示されません。

同じことは、ATOMフィードで起こっているが、そのページで指さ

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails').read)
(rdb:1) doc.class
Nokogiri::HTML::Document

私は、HTMLやフィード(RSSやATOM)のいずれか、それは事前に何であるか知らずにページを解析し、確実にそれがあるかを判断できるようにする必要があります。私は、HTMLやXMLフィードファイルのいずれかのボディを解析する鋸山を尋ねたが、私は、これらの矛盾した結果を見ています。

私はタイプを決定するためにいくつかのテストを書くことができると思ったが、その後、私は要素が見つからないのXPathに走ったが、作業を定期的に検索します:

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document
(rdb:1) doc.xpath('/feed/entry').length
0
(rdb:1) doc.search('feed entry').length
15

私は、XPathには、XMLで動作するだろうが、結果はどちらか信頼できる見えない考え出します。

これらのテストは、すべての私のUbuntuボックスで行ったが、私は私のMacBook Proの上で同じ動作を見てきました。私は私が何か間違ったことをやって見つけるのが大好きですが、私は私に一貫性のある結果が得られた解析および検索のための例を見ていません。誰かが私に私の方法のエラーを表示することができますか?

役に立ちましたか?

解決

これは動作しますの鋸山の解析方法方法に関係しています。ここではソースがあります:

# File lib/nokogiri.rb, line 55
    def parse string, url = nil, encoding = nil, options = nil
      doc =
        if string =~ /^\s*<[^Hh>]*html/i # Probably html
          Nokogiri::HTML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_HTML)
        else
          Nokogiri::XML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_XML)
        end
      yield doc if block_given?
      doc
    end

キーは、ラインif string =~ /^\s*<[^Hh>]*html/i # Probably htmlです。あなただけopenを使用する場合、それはこのように、それは常にfalseを返し、正規表現では動作しないオブジェクトを返します。一方、readは、文字列を返すので、それは、がHTMLとみなすことができます。それは正規表現にマッチするので、この場合には、あります。ここでは、その文字列の先頭があります:

<!DOCTYPE html PUBLIC

正規表現は[^Hh>]*する「!のDOCTYPE」にマッチして、これは、HTMLだと仮定すると、「HTML」と一致します。なぜ誰かがファイルをHTMLが私を超えているかどうかを判断するために、この正規表現を選択しました。この正規表現では、<definitely-not-html>のようなタグで始まるファイルはHTMLと考えられているが、<this-is-still-not-html>は、XMLと考えられています。おそらく、このダムの機能から離れて滞在し、直接Nokogiri::HTML::Document#parseまたはNokogiri::XML::Document#parseを呼び出すオフ最高です。

他のヒント

あなたの質問のこの部分に応えます:

  

私は、私はいくつかのテストを書くことができると思いました   タイプを決定するが、その後、私はに走りました   XPath要素を見つけることではなく、   ワーキング定期検索します:

私は、Atomフィードを解析する鋸山を使用して、この問題に遭遇しました。問題は、匿名の名前空間宣言にダウンしていました。

<feed xmlns="http://www.w3.org/2005/Atom">

ソースXMLからxmlns宣言を削除すると、通常通りのXPathで検索する鋸山を可能にします。フィードからその宣言を削除すると、明らかにここにオプションではありませんでしたので、代わりに私はパース後の文書から名前空間を削除しました。例えばます:

doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
doc.remove_namespaces!
doc.xpath('/feed/entry').length

醜い私が知っているが、それはトリックをやっています。

scroll top