くらひと様にコメントでご質問頂いた内容に関して、自分の備忘もかねて補足しておく。
というかホントのことをいうと、「目次」に関してはまったく頭が及んでなかったので、コメントに答える為に改めて見直してみたら「あ。できそうじゃん」と思い、ウソいってたらマズイので実際に試してみたというわけだ(笑)。 最終コマ数を取得する為に、ビューワの画面をGETしていることは既に述べたが、このページの中にはいわゆる「書誌情報」も含まれている。 また、このページはJavaScriptでインタフェイスを切り替えているだけで、元々1ページの中に目次の情報も含まれている。 例によって http://kindai.ndl.go.jp/info:ndljp/pid/1137942 このページをサンプルとする。 ブラウザでこのページのソースを表示してみると、そのhtmlの中に書誌情報・目次情報が埋め込まれていることが確認できる。 コメントにも書いたとおり;
PDFにはいくつか「目次」処理を行う手段があるが、ここではもっともノーマルな「しおり」(ブックマーク)として、ndltreeのデータを使うことを考えてみる。 何度も繰り返しているように、本来はこの部分は構造化文書(html.xml)としてきちんとパースするべきである。だが、残念なことに.netではいわゆる「HTMLパーサー」が標準としては提供されていない。 もちろんxmlパーサーで代用することは可能だろうが、近デジの提供するhtmlがvalidなxmlとして解釈できるかどうかがよく判らないし、真面目にhtmlパーサーを作ると面倒くさいので(爆)、例によって単なる検索で処理してみた。 まずはndltreeブロックの明細行を検索して、PDFの「しおり」付けに必要な最低限のデータ、startContentNoとtitleを取得する。 下の例で、DocHtmlは近デジ画面からGETしたhtmlを格納したString、TocInfoは startContentNo,Title のリストである。 string Reg_anchor = "<input type=\"hidden\" value=\"startContentNo=(?<startContentNo>.*?)\".+?class=\"ndltree-item ndltree-label\" title=\"(?<title>.*?)\">"; Regex re = new Regex(Reg_anchor, RegexOptions.IgnoreCase | RegexOptions.Singleline); System.Text.RegularExpressions.MatchCollection mc = re.Matches(DocHtml); foreach (System.Text.RegularExpressions.Match m in mc) { startNo = m.Groups["startContentNo"].Value; Title = m.Groups["title"].Value; TocInfo.Add(TocStartNo, TocTitle); } こんな感じで、startContentNoとtitleのリストを作る。 今回、俺はiTextSharpを使っているのだが、「しおり」生成のところはかなり悩んだ―というか、書き方がよく判らなかった(今でもよく判ってない)のだが、PDFを結合するために使用しているPdfCopyオブジェクトに、以下のダンドリで処理するとなんとなく上手くいくようである。 訂正:PdfDestinationの値がおかしかったので直した。ズームを継承するにはマイナスを入れろとドキュメントに書いてあるのでそのとおりにしたが、これでホントに良いのかどうか不安だなぁ。 ここで、copyオブジェクトはPdfCopy型であり、個別PDFを結合した結果が格納されている。 PdfContentByte cb = copy.DirectContent; PdfOutline root = cb.RootOutline; PdfWriter wrt = cb.PdfWriter; wrt.ViewerPreferences = PdfWriter.PageModeUseOutlines; // しおり開くモード PdfOutline oline = new PdfOutline(root, PdfAction.GotoLocalPage(1, new PdfDestination(0,-1.0F,-1.0F,0.0F), wrt), "Contents"); for (int i = 0; i < TocInfo.Count; i++) { PdfOutline oline1 = new PdfOutline(oline, PdfAction.GotoLocalPage(TocInfo[i].startNo, new PdfDestination(0,-1.0F,-1.0F,0.0F), wrt), TocInfo[i].title); } ようするに、copyオブジェクトのRootOutlineを取得し、そこにまずトップノード(ここでは"Contents"という見だし)を作成し、その配下(section)として、取得した目次情報を追加してしまう、という処理である。 PDFのOutlineオブジェクトはもちろん階層化できるのだが、どうも近デジデータはフラットなデータのようなので、そのまんまループで回して貼り付けている。 ということで、この機能を追加してはき出させたPDFはこうなる。 ![]() なるほど、ある種の文書はやっぱり目次があった方が圧倒的に便利である。 気づかせて下さった くらひと様 に感謝申し上げます。
by signal-9
| 2012-07-24 13:49
| TIPSとかKludgeとか
|
カテゴリ
全体 一般の話題 奇妙な論理 奇談・異聞 秋葉原 研究(笑) 町歩き 古い話 東電災害 電算機関係の話題 情報保護・セキュリティ 読んだり見たり TIPSとかKludgeとか 拙作ソフトウェア 未分類 最新の記事
記事ランキング
以前の記事
最新のトラックバック
その他のジャンル
ブログジャンル
画像一覧
| ||||||||||||||||||||
ファン申請 |
||