PHP が HTML コード文字列をインターセプトする

WBOY
リリース: 2016-06-21 08:57:23
オリジナル
1143 人が閲覧しました

需求:将一段文字截取一定的物理长度显示,注意,要截取的不是字符串的字节数,UFT-8 的编码中文字符是3个字节或者4个字节的,而显示的时候中文会占两个字符的长度,英文字符只占一个,全角的时候又有不同。

需求:将一段文字截取一定的物理长度显示,注意,要截取的不是字符串的字节数,UFT-8 的编码中文字符是3个字节或者4个字节的,而显示的时候中文会占两个字符的长度,英文字符只占一个,全角的时候又有不同。而且给的数据是HTML代码串,比如这样:

インターセプトするときは、div タグ内のコンテンツをインターセプトし、HTML タグを保持し、その中のテキストのみを処理する必要があります。たとえば、「李思」の「李」という単語をインターセプトするだけかもしれませんが、このようにフロントエンドに置くと、「李思」の前の a タグが閉じられないので、インターセプト後に、 HTML 構文が正しいことを確認する必要があります。

この問題は本当に解決するのが簡単ではなく、私は二日間憂鬱になりました。これは単なる文字列ですが、内容は HTML コードであり、DOM がないことに注意してください。フロントエンドで処理できれば、DOM を直接取得して内部のノードを処理し、最終的に innerHTML などを出力することができます。今はうまくいかないので、考えを変えなければなりません。私の同僚の考えは次のとおりです:

文字列の各文字をループします。タグを設定し、タグの先頭で < タグが見つかった場合は 1 に設定し、その後の文字はカウントされません。ラベル内の文字列を処理するときは、まず現在の文字エンコーディングが中国語であるかどうかを判断する必要があります。一般に、PHP で UTF-8 でエンコードされた中国語の文字の長さは 3 です。したがって、中国語の文字エンコーディングが見つかった場合は、次のようにする必要があります。カウントされていないものを 2 つスキップします... この時点で、私の頭は大きくなり始めています。個人的には、この方法は非常に不快だと思います。第一に、この種の絶妙なロジックは制御が容易ではありません。また、UFT-8 エンコーディングで生成される中国語の長さは 3 または 4 になる可能性があります ため、厳密性は高くなります。コードに疑問があります。

私の個人的なアイデアは、Tidy を使用することです (具体的な使用方法については、PHP マニュアルを参照してください)。昨日Tidyについて勉強したところ、これがとても便利であることがわかりました。まず、この文字列を次のように Tidy オブジェクトに変換します。

$tidy = tiny_parse_string($str, array(), 'utf8'); // 最後の設定は、utf-8 ではなく、utf8 であることに注意してください。 、いいえ、真ん中のものです。

次に $tidy で本文を取得します ($tidy は変換後に などのタグを自動的に追加するため):

$body = tiny_get_body($tidy);

現時点では、var_dump を使用して $body 構造をいくつか確認すると、各タグが対応する属性を持つ対応するオブジェクトに変換されることがわかります。たとえば、 sdfname=>「a」

値 => “sdf
child=> 配列{[0]=>テキスト ノード オブジェクト、値は sdf}
属性=配列{”href”=>”#”}
…..その他の属性

ご覧のとおり、実際には、a タグに対応するノードの下にあるテキスト ノードの値を個別に処理できるため、HTML の整合性は損なわれません。本来は、aタグ内のテキストノードの値を変更すると、それに合わせてaタグの値も変更されると考えていましたが、その場合はaに対応するノードの値を直接返せば良いのではないかと考えていました。残念ながら、そのようなものになるとは予想していなかったので、その中のテキストを自分で記述する必要がありました。

Tidy オブジェクトの構造を理解した後は、すべてのノードを走査するだけで、div タグを見つけて内部のノードの処理を開始するだけで済みます。コードは次のとおりです:

if(mb_strwidth($subchild->value, ‘utf-8’) >= $len)

{
$subchild->value = mb_strimwidth($subchild->value, 0, $len, ‘…’, ‘utf-8’);
$trimed_str .= $subchild->value;
休憩;
}
それ以外
{
$trimed_str .= $subchild->value;
$len = $len - mb_strwidth($subchild->value, ‘utf-8’);
}

内部の $subchild は子ノードです。ここでは文字列の長さを取得するために

mb_strwidth が使用されていることに注意してください。 mb_strwidth を強くお勧めします。これは中国語を 2 文字の長さとして扱うので、ここでのニーズを正確に満たします。さらに、文字列をインターセプトするときに mb_strimwidth が使用されます。この関数は中国語も 2 文字の長さとして扱います。 mb_ で始まる関数は非常に使いやすいです。

具体的なコードは書きません。これは要件に基づいて書かれており、普遍的な形式に作られていないからです。いつかそれを普遍的なものにして公開する時間ができました。

さらに、FireFox が text-overflow 属性をサポートしていないのは残念です。サポートしていなければ、バックグラウンドで苦労して切り詰める必要はありません。もっと良い方法があれば、ぜひ提案してください!ご協力をよろしくお願いいたします。



関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート