「ドキュメントを見た」とのことでご存じかと思われますが、Nokogiriは取得したノードの行のみですが位置は取得できます。ただしオリジナルではありません。
畑が違いますがPythonのlxmlライブラリだとオリジナルからノードの行数に限り得ることができますので、後は列数検索を独自実装することで目的に近いことは可能になるかもしれません。ご参考までに。
HTML が与えられ,その中の特定のノードを CSS パスや XPath で探し出し,当該箇所の位置を知るにはどうすればいいでしょうか。
例えば以下のような HTML があるとします。
<!-- 前略 -->
<ul>
<li>foo</li>
<li class="hoge">bar</li>
</ul><!-- 後略 -->
このような HTML において,クラス hoge
を持つ要素,つまり,
<li class="hoge">bar</li>
が,HTML テキスト上で何文字目から何文字目まで占めているか,といったことが知りたいのです。
なお,「ノード」と書きましたが,想定しているユースケースではほぼ確実に要素なので「要素」と読み替えていただいても大丈夫です。
HTML テキストに対し,文字列ベースでの加工を施したいのですが,加工箇所を HTML パーサーで絞りたいのです。正規表現で絞るのは極めて困難(現実には不可能)なので。
HTML のパーサーとして Nokogiri を用い,Nokogiri::HTML::Document の css
メソッドや xpath
メソッドで要素を得るのは簡単にできます。
しかし,得たノードは,「HTML テキスト上でどの位置を占めていたか」という情報を持っていないようです。
ドキュメントを見たのですが,そういう情報が取り出せそうなメソッドが見当たりませんでした。
Nokogiri の他には Oga というパーサーを検討しましたが,やはりそのようなメソッドは見つけられませんでした。
次に考えたのが,特定したノードの HTML 表現を使って検索をかけることでした。
しかし,Nokogiri のノードは,元の HTML を得る機能も持っていないようでした。
to_html
メソッドはありますが,これは HTML を再構築する機能であり,元と同じものが再現できるとは限りません。
たとえば,
<img src="foo.png"
class='bar'>
は
<img src="foo.png" class="bar">
にされてしまいます。
「ドキュメントを見た」とのことでご存じかと思われますが、Nokogiriは取得したノードの行のみですが位置は取得できます。ただしオリジナルではありません。
畑が違いますがPythonのlxmlライブラリだとオリジナルからノードの行数に限り得ることができますので、後は列数検索を独自実装することで目的に近いことは可能になるかもしれません。ご参考までに。
@scivola
QuestionerNokogiri::XML::Node#line は存在に気づいてませんでした。CRuby 版だとオリジナルの行番号が取れるようですね。
ありがとうございます。
まさしく正規表現で置換なんてことを不要にするためのDOMパーサーを用いてレスポンステキストレベルの加工をしようとすること自体根本的な矛盾を感じますがいかがでしょうか.
そもそもスクレイピングか何かが目的とお見受けしますが,DOMを使って特定ノードの情報が取り出せるならそれ以上溯ること自体が無駄でしょう.
ノードの除去という点でもDOMが使えるならわけないです.
元文書の保全を目的としている場合は,むしろ下手に手をつけてしまうと処理的ないし情報規約的にまずい場合が多いです.
@scivola
Questionerご心配には及びません,ありがとうございます。
心配というか普通は必要ないことをしているように見えるのです.できれば背景を補足願えませんか.
@scivola
QuestionerHTML ファイルの加工をするのですが,その際,修正箇所以外は文字列(HTML テキスト)として温存するという要件があります。
「DOM 的に同じ HTML は同じものを表しているんだから変わったっていいだろう」とか「その要件自体おかしい」というツッコミにはお答えしかねます。
ま,いずれにしても一般のDOMパーサーを用いたところで基本的に元のテキストには介入できないので,現状のアプローチで要件を満たすのは厳しいと思われます.
幸いソースは公開されているので,Nokogiriのそれっぽいところを参考に実装するしかないです.