2013年3月19日火曜日

PythonのSAXで外部DTDを読みたくない

掲題の通り。

DTDにインターネットへの参照が

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
のようにあると、オフラインではファイルを取得できずにエラーとなってしまいます。DTDの中身を見たいわけでもないときには非常に残念です。

いまどきオフラインでの開発はほとんどありませんが、精神衛生上よろしくないので解決策を調べておくと、

from xml.sax import make_parser
from xml.sax.handler import feature_external_ges

parser = make_parser()
parser.setFeature(feature_external_ges, False)
f = open('some_file.xml')
parser.parse(f)
f.close()

feature_external_gesFalseにしてあげるだけでよいようです。

EntityResolverを用いて、あらかじめダウンロードしておいたDTDを参照することでもエラーを解消できます。

from xml.sax import make_parser
from xml.sax.handler import EntityResolver

class MyEntityResolver(EntityResolver):
    def resolveEntity(self, publicId, systemId):
        # ローカルに保存したDTDを開く
        return open(systemId.split('/')[-1], 'rb')

parser = make_parser()
parser.setEntityResolver(MyEntityResolver())

f = open('some_file.xml')
parser.parse(f)
f.close()

2013年3月6日水曜日

Viz.jsで日本語出力

Graphvizの出力をJavaScriptだけで手軽に得られるVis.js。ラベルに日本語を使うとエラーが出たので、ムリクリ動かしてみました。
example.htmlをいじって↓のグラフを表示してみます。まずは日本語なしで。
digraph G {

 subgraph cluster_0 {
  style=filled;
  color=lightgrey;
  node [style=filled,color=white];
  a0 -> a1;
  label = "process #1";
 }

 subgraph cluster_1 {
  node [style=filled];
  b0 -> b1;
  label = "process #2";
  color=blue
 }
 start -> a0;
 start -> b0;
 a0 -> b1;
 a1 -> end;
 b1 -> end;

 start [shape=Mdiamond];
 end [shape=Msquare];
}

すばらしいですね。
さっそくstartのラベルを日本語に変更してみます。
 start [label="はじめ" shape=Mdiamond];

ラベルはちゃんと変わったもののエラーが…
日本語を入れるとグラフソースの終わり位置の計算が狂うような動きをしています。 もうそこソースじゃないっすよ、というところまでグラフだと思って読んでしまってエラーが出ているようです。
そこでexample.htmlの、
function src(id) {
  return document.getElementById(id).innerHTML;
}
を変更して、グラフのソースにたっぷりと空白をつけて先に進みすぎても大丈夫なように、
function src(id) {
  var dot = document.getElementById(id).innerHTML;
  return dot + new Array(dot.length).join(" ");
p}
としてみると、

きれいに表示できましたとさ。

2013年3月5日火曜日

Pythonで中国語をピンインに (xpinyin)

xpinyinを使うとこんな感じです。

1. インストール

pip install xpinyin

2. 使う

from xpinyin import Pinyin
p = Pinyin()

print p.get_pinyin(u'个')
=> 'ge'

おおざっぱに読みを知りたいときによさそうですね。