質問の動機は、以下のセクションに描かれています。 テキストをイタリックにする多くの方法 があるため、おそらく1つ以上の良い "swap イタリックアルゴリズム "。この問題は、XHTMLコードにいくつかの追加の難しさを示しており、_<i>
_タグを使用していますバランスを取る必要があります。例:
_ <!-- original text: -->
<p id="p1"><i>Several more</i> Homo sapiens <i>fossils were discovered</i>.</p>
<!-- same text, swapping italics: -->
<p id="p2">Several more <i>Homo sapiens</i> fossils were discovered.</p>
_
このように見えます
さらに数個ヒト化石が発見されました。
さらにいくつかのホモサピエンスの化石が発見されました。
"layout solution"の場合、最も簡単なアルゴリズムは、すべてのテキストブロックの_font-style
_ CSSプロパティをチェックし、jQueryで反転します。
_$('#myFragment *').each(function(){
if ($(this).css('font-style')=='italic')
$(this).css('font-style','normal')
else
$(this).css('font-style','italic')
});
_
しかし、このアルゴリズムはもう少し複雑なテストに耐えられません。
_ <p id="p3"><b><i>F</i>RAGMENT <big><i>with italics</i> and </big> withOUT.</b></p>
_
2番目に単純なアルゴリズムはコンクリートソリューション用であり、「例」セクションで使用されました。 2つのステップがあります。
</i>
_から_<i>
_)。つまり、Javascriptで書く、
_var s = '... a fragment of XHTML content ...';
s = '<i>'+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
'</i>';
_
しかし、タグのバランスを失って、2番目のテストにも耐えられません...「修正された」アルゴリズムは実行されますが(!)、移植性がなく、高速でもエレガントでもありません。それは ここに示されています であり、以下の例のセクションにあります。
だから問題は、
シンプルで優れた汎用的な(どのブラウザでも使用可能で、他の言語に移植できる)アルゴリズムはありますか?別の「スワップイタリックアルゴリズム」を知っていますか?
PS:私があなたのアルゴリズムをXSLTに変換するという意味での「一般的な」。アルゴリズム直接生成する必要があります バランスのとれたXHTMLコード(Tidyのような中間ブラックボックスなし)。
「スワップイタリックアルゴリズム」をテキストエディター、サーバーパーサーなどに移植する必要があります。すべてのケースで、標準のXHTMLおよび_<i>
_タグによって「入力(および出力)を正規化」できます。
私は、さまざまな起源とスタイルからエクスポートされた散文の本と科学記事のXHTMLテキストを解析しています...ほとんどのテキストは「通常のテキスト」としてエクスポートされますが、多くのタイトル(例:記事のタイトル、章のタイトル)、そして時には、完全な章または完全なテキストボックス(記事の要約など)は、イタリック体で様式化されています。これらすべての「イタリックで様式化された」は、逆にする必要があります。典型的なケース:
元の「すべての章のイタリック」を「すべての章の通常のテキスト」に変換します: この場合を参照 。約300ページの書籍では、25の章のうち8つの章を反転する必要があります。
イタリック体の引用符、要約など。 この例 を参照してください。通常に戻す必要がありますが、強調の言葉を失うことはありません。
科学的テキストでの 種の二項名 の記述は、通常、イタリック体でタイプセットされます(または「通常のテキスト」で使用されるものとは異なるフォントで反転されます)。 XHTMLでエクスポートされた記事の(記事および記事セクションの)斜体の何百ものタイトルを職場で反転させる必要があります。 PS:質問の最初の例を参照してください(「さらにいくつかHomo sapiens...」)。
「タグバランス修正」が存在しない(答えの)汎用アルゴリズムをXSLTライブラリに変換するも必要です。
JavaScriptおよびPHP a non-generic "イタリックアルゴリズムをスワップする"で実装します。一般的なものには、一般的な "XMLインターリーブアルゴリズム"が必要です...ここでは、ブラウザの( DOM)とTidy修正、「インターリーブ」の代替手段として。
複雑な入力(!)で実行されます。説明 jQuery実装 :
_ var s = $('#sample1').html(); // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
s = "<i>"+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
"</i>"; // a not-well-formed-XHTML, but it is ok...
$('#inverted').html(s); // ...the DOM do all rigth!
// minor corrections, for clean empties:
s = $('#inverted').html();
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean remain
$('#inverted').html(s);
// END ALGORITHM
alert(s);
_
PHP=に「翻訳」されたJavascriptと同じ—自然な翻訳はDOMDocument()
クラスとloadHTML
/saveXML
メソッドを使用していますが、ブラウザのコレスポンデントと同じ動作をするのは tidy
class です。同じ結果を表示します(!)
_ $sample1='<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>';
$inverted = '... inverted will be here ...';
echo $sample1;
// Tidy correction
$s = $sample1; // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
$s = "<i>".
preg_replace_callback('/<(\/?)i>/s', function ($m){
return $m[1]? '<i>': '</i>';}, $s) .
"</i>"; // a not-well-formed-XHTML, but it is ok...
$config = array('show-body-only'=>true,'output-xhtml'=>true);
$tidy = new tidy;
$tidy->parseString($s, $config, 'utf8');
$s = $tidy; // ... because Tidy corrects!
// minor corrections, for clean empties:
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean remain
// END ALGORITHM
echo "\n\n$s";
_
更新(2013年6月18日):この回答を使用してアルゴリズムを説明し、結論を要約します。
JQueryトラバースと「レイアウトソリューション」の回避策について。
@Wilbertのコメントの後、check .prop()
の反復により変化する.each()
の動的動作を回避するために、「最も単純なアルゴリズム」を採用し、else
を削除しました。すべての反復の後、「親イタライザ」が解決します。 ここを参照 または以下のコード。
_$('#myFragment *').each(function(){
if ($(this).css('font-style')=='italic')
$(this).css('font-style','normal');
});
$('#myFragment').parent().css('font-style','italic');
_
動的な振る舞いを処理する別の方法は、prop('tagName')
を使用して、変更されない静的プロパティをチェックすることです。 ここを参照 または以下のコード。
_$('#myFragment').parent().css('font-style','italic');
$('#myFragment *').each(function(){
if ($(this).prop('tagName')=='I') // not changes with parent
$(this).css('font-style','normal');
});
_
より多くのテストが必要で、スタイルプロパティを具体的な_<i>
_タグに変更するには、最終的な解析が必要です。アルゴリズムを2回適用するには、注意が必要です。
これは現在の質問の解決策ではありませんが、いくつかの良い手がかりを生み出し、は「レイアウトの問題」の最良の(少なくとも最小!)解決策です!
toggleClass()
method を使用して、「イタリック体のクラス」から「通常のテキストクラス」にswapできます。 ここを参照 または以下のコード。
_ $('#myFragment *').each(function(){
$(this).toggleClass( "original change");
});
_
そして、この小さなアルゴリズムを2回、そして必要なだけ何度でも適用できます...これは良い解決策です!しかし、これは「rewrite XMLアルゴリズム」ではなく、ここでCSSが鍵となります:
_ .original { font-style:normal; } /* use class="original" in your XHTML fragment */
i.original { font-style:italic; }
.change { font-style:italic; }
i.change{ font-style:normal; }
_
...したがって、_<i>
_タグを変換するアルゴリズムの場合、問題は未解決のままです...
@ DanielHaleyの修正 に基づく「純粋なXSLT1での100%ソリューション」(多くのケースでテストされています!)これは、効果的な_<i>
_タグ変換です。
_ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="p"/>
<xsl:template match="@*|node()"> <!-- copy all -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="i"> <!-- remove tag i -->
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[not(ancestor::i)]"> <!-- inlcude tag i -->
<i><xsl:copy-of select="."/></i>
</xsl:template>
</xsl:stylesheet>
_
コピープロセスの「ドライブバイイベントアルゴリズム」としての概要:
i
タグを削除:「_<i>
_thing_</i>
_」のすべてのものを「thing "。
i
タグを含める:任意のtextを「_<i>
_text_</i>
_」としてコピーします、textがイタリックの親のコンテキストに含まれていない場合。 PS:textはDOMツリーのターミナルノードです。
「レイアウトソリューション」は テキストエディター に適していますが、いくつかのトリックと厳密でないソリューションを使用しています(オーバーラップ、パフォーマンスなどは関係ありません)。 XMLプロセスでは、_<i>
_タグの変換を処理する必要があります...したがって、アルゴリズムを表現するための自然言語はXSLTまたはxQueryです。
XSLTで実装されたアルゴリズムは、フレームワークの必要性を示しています。
ancestor(親、祖父母など)セレクタ。「イタリックコンテキスト」かどうかを確認します。
テキストノード(DOM text()
)アクセス。
i
タグを削除して含めます。
したがって、各フレームワークの問題を確認できます。
[〜#〜] dom [〜#〜] (W3C標準フレームワーク):項目3のDOMDocument::renameNode()
はまだ実装されていません(PHP、Javascriptなどを参照)。 )。
jQuery:項目2には便利な関数がありません この答え を参照してください。
XSLT:アルゴリズムを表現するのに最適ですが、JavaScriptなどのコンテキストでは使用できません。
私(またはあなたが言いました!)は、「純粋なDOM2」メソッドでXSLTアルゴリズムを表現しようとします。そのDOMバージョンは「一般的なアルゴリズム」になります...さて:変換がDOM3に対してのみ有効である場合(renameNodeやその他のトリックを使用)、現時点での結論は「一般的な/翻訳可能なアルゴリズムは存在しない」ということです。
https://stackoverflow.com/a/17156452/317052 からのXSLT試行...
これがすべてのケースをカバーするかどうかはわかりませんが、これを行うことができます:
XML入力
<html>
<!-- original text: -->
<p id="p1"><i>Several more</i> Homo sapiens <i>fossils were discovered</i>.</p>
<!-- same text, swapping italics: -->
<p id="p2">Several more <i>Homo sapiens</i> fossils were discovered.</p>
<p>Leave me alone!</p>
<p><b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b></p>
</html>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[i]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" mode="swapItal"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" mode="swapItal" priority="1">
<i><xsl:value-of select="."/></i>
</xsl:template>
<xsl:template match="i" mode="swapItal">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="@*|node()" mode="swapItal">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="swapItal"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML出力
<html>
<!-- original text: -->
<p id="p1">Several more<i> Homo sapiens </i>fossils were discovered<i>.</i></p>
<!-- same text, swapping italics: -->
<p id="p2"><i>Several more </i>Homo sapiens<i> fossils were discovered.</i></p>
<p>Leave me alone!</p>
<p><b>O<i>RIGINAL </i><big>with italics<i> and </i></big><i> withOUT</i></b></p>
</html>
レンダリングされた入力
さらにいくつか ホモサピエンス 化石が発見された。
ホモサピエンスほっといて!
O元の 斜体 そしてwithOUT
レンダリングされた出力
さらにいくつか ホモサピエンス 化石が発見された。
さらにいくつか化石が発見されました。ほっといて!
O元の 斜体 そしてwithOUT