2012-04-26 9 views
5

デフォルトでは、lxmlは長い単語で単語区切りを追加するために使用されるwbrタグには対応していません。これは、<wbr>という形式で、brタグと同様にフォーマットする必要がある場合は、<wbr></wbr>という形式になります。lxmlと<wbr>タグ

lxmlにこの動作を追加するにはどうすればよいですか?

+1

あなたのアプリケーションはわかりませんが、終了タグを削除するだけでいいですか? –

答えて

10

は、実際にはパッチlibxml2のテストプログラムwbr_test.pyを定義

まず(このチュートリアルは、Python 2.7.3とUbuntuの11.04で行われました)には難しいことではありません実行中python wbr_test.py <\body>の前に<\wbr>を挿入し、最後にnot okを印刷する必要があります。

ダウンロードし、抽出液とlibxml2をコンパイル:

wget ftp://xmlsoft.org/libxml2/libxml2-2.8.0.tar.gz 
tar xvf libxml2-2.8.0.tar.gz 
cd libxml2-2.8.0/ 
./configure --prefix=/usr 
make -j8 # adjust number to match your number of cores 

インストール、およびPythonのlibxml2のバインディングをインストールします。

sudo make install 
cd to_python_bindings 
sudo python setup.py install 

は確かにそれが最新のlibxml2のバージョンで失敗するために、もう一度あなたのwbr_test.pyをテストします。

最初にHTMLparser.cのコピーを作成します。 /var/tmp

ここで、HTMLparser.cファイルをlibxml2ソースの最上位に編集します。単語forced(1回のみ)を検索します。 <br>タグ定義になります。今見つかった行から3行をコピーします。最も適切な挿入ポイントは、末尾の直前(<var>の定義の後)です。テーブルの最後のカンマを取得するには、'}'のあるものの前に3行を挿入し、'};'のものは挿入しないでください。新たに挿入されたコードで

wbrbrを交換し、(新たなタグが廃止予定の属性を持っていないと仮定して)NULLDECL clear_attrsを変更します。

結果は次のように/var/tmpdiff -u HTMLparser.c /var/tmp)にバージョンでdiffをする必要があります

@@ -1039,6 +1039,9 @@ 
}, 
{ "var", 0, 0, 0, 0, 0, 0, 1, "instance of a variable or program argument", 
DECL html_inline, NULL, DECL html_attrs, NULL, NULL 
+}, 
+{ "wbr", 0, 2, 2, 1, 0, 0, 1, "possible line break ", 
+ EMPTY , NULL , DECL core_attrs, NULL , NULL 
} 
}; 

メイクをしてインストールします。

make && sudo make install 

をもう一度あなたのwbr_test.pyをテストします。 OK

+0

非常にクール!ランタイム構成だけで類似の結果を得る方法がないことを確認できますか? – bukzor

+0

同じ質問にフレーズを変える方法はありますか?libxml2はパッチしたリストの実行時設定を許可しませんか? – bukzor

+0

ソースを再構築することなくlibxml2で可能であるかどうかは本当に驚くでしょう。定義は静的なconst要素表にありますが、これはより動的な構造にコピーされませんが、そのまま使用されます。このようなテーブルへのエントリの追加はCでは不可能であり、したがってPythonでは不可能です。 – Anthon

3

<wbr>はHTML5にのみ存在するので、私は正しいことがlxml.html.html5parserであると思われます。

これを除いて、空のタグのリストは通常​​のPythonコードで定義されているので、いつでもそれをmonkeypatchできます。 lxml.html.defs.empty_tagsを参照してください。パッチは歓迎です、私は確信しています。 :)

+0

私は、効果がないように、モンキーパッチを試みました。 – bukzor

+0

@bukzor: 'br'も 'special_inline_tags'にあります...あなたも同様に 'wbr'をmonkeypatchする必要があります。 –

+1

'defs'を最初にインポートし、lxmlに何か他のものをインポートする前にそれをmonkeypatchしなければならないかもしれません、または他のモジュールは古い値をインポートしました。 – Eevee

5

良いニュース!これは全く不可能です。 HTMLタグ名はbaked right into libxml2です。

lxml.html.html5parserには、修正がまだリリースされていない重大なバグがいくつか含まれています。

でも、地元の人たちを修正して、どうなるか見てみましょう。

>>> lxml.html.tostring(lxml.html.html5parser.fromstring('<p>hello<wbr>world!</p>'), encoding=unicode) 
u'<html:p xmlns:html="http://www.w3.org/1999/xhtml">hello<html:wbr></html:wbr>world!</html:p>' 

だからまだ近い。構造は正しいです、少なくとも。

もう一つの試み:

>>> lxml.html.tostring(lxml.html.html5parser.fromstring('<p>hello<wbr>world!</p>', parser=lxml.html.html5parser.HTMLParser(namespaceHTMLElements=False)), encoding=unicode) 
u'<p>hello<wbr></wbr>world!</p>' 

Welp。

は、少なくともではありません。

私はlxmlとlibxml2に対していくつかのバグを報告するかもしれないと思います。

from lxml import etree 
from cStringIO import StringIO 

wbr_html = """\ 
<html> 
    <head> 
    <title>wbr test</title> 
    </head> 
<body> 
    Test for a breakable<wbr>word implemenation change 
</body> 
</html> 
""" 

parser = etree.HTMLParser() 
tree = etree.parse(StringIO(wbr_html), parser) 

result = etree.tostring(tree.getroot(), 
         pretty_print=True, method="html") 
if result.split() != wbr_html.split(): # split, as we are not interested in whitespace differences 
    print(result) 
    print("not ok") 
else: 
    print("OK") 

することがで失敗したことを確認してください:

1

クイックフィックスとして、replaceストリングのメソッドを使用してクローズタグを削除してみませんか?

>>> t = 'Thisisa<wbr></wbr>test' 
>>> t.replace('</wbr>', '') 
'Thisisa<wbr>test'