HTMLのrubyタグをパースして青空文庫のルビ注記に変換する。ただし、rbタグがあることを前提に作られたHTMLパーサーだとおかしなことになる。AozoraEpub3のrubyタグのパーサー部分を見るとrbタグがあることが前提で書かれている。
/** ルビを青空ルビにして出力 */ private void printRuby(BufferedWriter bw, Element ruby) throws IOException { Elements rb = ruby.getElementsByTag("rb"); Elements rt = ruby.getElementsByTag("rt"); if (rb.size() > 0) { if (rt.size() > 0) { bw.append('|'); printText(bw, rb.get(0).text()); bw.append('《'); printText(bw, rt.get(0).text()); bw.append('》'); } else { printText(bw, rb.get(0).text()); } } }
どういう場合分けがいいのか、rubyタグ内にrbタグがなかったら、textエレメントがあるのかと思ったらnodeNameの#textを見る。ただし、Javaでも同じようには書けなかった。Javaではテキストはテキストノードで、エレメントと別に書かれていた。
ブラウザで可能なテスト要素に書き換えるとモノルビでは対応できてなさそう。ものルビを使っている小説投稿サイトがまずないのだが、rbタグを廃止している傾向がある。
// rubyタグ let html = "<ruby><rb>漢</rb><rb>字</rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp></ruby>" let parser = new DOMParser(); let doc = parser.parseFromString(html, "text/html"); ruby=doc.getElementsByTagName("ruby")[0] rb= ruby.getElementsByTagName("rb") rt=ruby.getElementsByTagName("rt") bw="" if(rb.length){ if(rt.length){ bw=bw + '|' + rb[0].textContent+'《'+rt[0].textContent +'》' } else{bw=bw + rb[0].textContent } }
モノルビに対応するにはforループを使ってみる
let html = "<ruby><rb>漢</rb><rb>字</rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp></ruby>" let parser = new DOMParser(); let doc = parser.parseFromString(html, "text/html"); ruby=doc.getElementsByTagName("ruby")[0] rb= ruby.getElementsByTagName("rb") rt=ruby.getElementsByTagName("rt") bw="" if(rb.length){ if(rt.length){ for(var i=0; i<rb.length; i++) { bw=bw + '|' + rb[i].textContent+'《'+rt[i].textContent +'》' } } else{bw=bw + rb[0].textContent } }
次はrbタグがないときの処理
let html = "<ruby>漢<rp>(</rp><rt>kan</rt><rp>)</rp>字<rp>(</rp><rt>ji</rt><rp>)</rp></ruby>" let parser = new DOMParser(); let doc = parser.parseFromString(html, "text/html"); ruby = doc.getElementsByTagName("ruby")[0] rb = ruby.getElementsByTagName("rb") rt = ruby.getElementsByTagName("rt") bw = "" if (rb.length) { if (rt.length) { for (let i = 0; i < rb.length; i++) { bw = bw + '|' + rb[i].textContent + '《' + rt[i].textContent + '》' } } else { bw = bw + rb[0].textContent } } else { for (let i = 0; i < ruby.childNodes.length; i++) { switch (ruby.childNodes[i].nodeName) { case '#text': bw = bw + '|' + ruby.childNodes[i].textContent break; case 'RP': break; case 'RT': bw = bw + '《' + ruby.childNodes[i].textContent + '》' break; case 'RB': bw = bw + '|' + ruby.childNodes[i].textContent break; default: console.log("未定義"); } } }
switch caseだけで統一できるかなと思ったんだけど、rb,rb,rt,rtという順番の場合にパースができないので複雑になってしまった。モノルビではなかったらswitch caseだけでよさそう
モノルビなどrbタグがあったりなかったり、rpタグ内は見ない。
<ruby>漢<rp>(</rp><rt>kan</rt><rp>)</rp>字<rp>(</rp><rt>ji</rt><rp>)</rp> </ruby> <ruby><rb>漢</rb><rp>(</rp><rt>kan</rt><rp>)</rp><rb>字 </rb><rp>(</rp><rt>ji</rt><rp>)</rp> </ruby> <ruby> <rb>漢</rb><rb>字 </rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp> </ruby>
html2aozoraでrb,rb,rt,rtという順番の場合にパースができてない。パーサーを作るのが難しい。 github.com