Webページで有効なXMLを編集するにはどうすればよいですか?
-
04-07-2019 - |
質問
手早く汚れた設定エディタを起動して実行する必要があります。フローは次のようになります。
構成(サーバー上のPOCO)はXMLにシリアル化されます。
この時点でXMLは整形式です。設定はXElementsでWebサーバーに送信されます。
Webサーバーでは、XML(はい、ITのすべて)が編集のためにテキストエリアにダンプされます。
ユーザーは、WebページでXMLを直接編集し、[送信]をクリックします。
応答では、XML構成の変更されたテキストを取得します。この時点で、すべてのエスケープはウェブページに表示するプロセスによって元に戻されています。
文字列をXMLオブジェクト(XmlElement、XElementなど)にロードしようとしました。 KABOOM。
問題は、シリアル化が属性文字列をエスケープすることですが、これは途中で翻訳では失われます。
たとえば、正規表現を持つオブジェクトがあるとします。 Webサーバーの設定は次のとおりです。
<Configuration>
<Validator Expression="[^<]" />
</Configuration>
だから、私はこれをテキストエリアに入れて、ユーザーには次のようにします:
<Configuration>
<Validator Expression="[^<]" />
</Configuration>
したがって、ユーザーはわずかな変更を加え、変更を送信します。 Webサーバーでは、応答文字列は次のようになります。
<Configuration>
<Validator Expression="[^<]" />
<Validator Expression="[^&]" />
</Configuration>
したがって、ユーザーは別のバリデーターを追加し、両方が不正な文字を持つ属性を持つようになりました。これを任意のXMLオブジェクトにロードしようとすると、<!> lt;が原因で例外がスローされます。および<!> amp;テキスト文字列内では無効です。私はすべての血まみれのものをエンコードするので、いかなる種類のエンコード関数も使用できません:
var result = Server.HttpEncode(editedConfig);
結果
<Configuration>
<Validator Expression="[^<]" />
<Validator Expression="[^&]" />
</Configuration>
これは有効なXMLではありません。これをあらゆる種類のXML要素にロードしようとすると、落下する金床にぶつかります。アンビルが落ちるのは好きではありません。
SO、疑問が残ります...この文字列XMLをXMLオブジェクトに解析する準備をする唯一の方法は、正規表現の置換を使用することですか? <!> quot;制約を無効にする<!> quot;ロードするとき?これをどうやって回避しますか?
有効な答えがあるとは思わないので、最後の1つの応答、次にこれをwiki化してください。
textareaに配置したXMLは有効なエスケープされたXMLです。 1)テキスト領域に入れる2)クライアントに送信する3)クライアントに表示する4)フォームに送信する5)サーバーに送り返す6)フォームから値を取得するREMOVESすべてのエスケープ。
これをもう一度言わせてください。私は何も逃げていません。ブラウザで表示するだけです!
熟考すること:そもそもこの脱出が起こらないようにする方法はありますか?ほぼ有効なXMLと<!> quot; clean <!> quot;を取得する方法はありますか?安全な方法で?
この質問には、今や恩恵があります。賞金を集めるために、正規表現を使用して属性値を手動でエスケープする必要がなく、ユーザーが属性をエスケープする必要がないサードパーティ/オープンソースツールなしで、ブラウザウィンドウで有効なXMLを編集する方法を示します。往復(<!> amp; amp; amp; amp; amp; etc;)
のときに失敗しません解決
Erm <!>#8230; <!> nbsp; どのようにシリアライズしますか?通常、XMLシリアライザーは無効なXMLを生成することはありません。
更新に応じて/ EDIT:編集するユーザーに無効なXMLを表示しないでくださいしない!代わりに、適切にエスケープされたXMLをTextBoxに表示します。壊れたXMLの修復は楽しくなく、実際には、有効なエスケープされた形式でXMLを表示/編集しない理由はありません。
もう一度質問することができます:どのように XMLをTextBoxに表示しますか?ある時点で意図的にXMLをエスケープしているようです。
最新のコメントに対する/ EDIT:はい、もちろん、HTMLを含めることができるためです。 XMLをHTMLページに書き出す前に、適切にエスケープする必要があります。それで、私は全体 XMLを意味します。だからこれ:
<foo mean-attribute="<">
これになります:
<foo mean-attribute="&<">
他のヒント
もちろん、テキスト領域内にエンティティ参照を配置すると、エスケープされずに出てきます。テキストエリアは魔法ではありません、あなたは<!> amp; escape;他のすべての要素と同じように、あなたがそれらに入れるものすべて。ブラウザは生の「<!> lt;」を表示する場合がありますテキストエリアにありますが、それは彼らがあなたの間違いを片付けようとしているからです。
したがって、編集可能なXMLをテキストエリアに配置する場合、属性値を一度エスケープして有効なXMLにし、次にXML全体を再度エスケープして有効なHTMLにする必要があります。ページに表示する最終的なソースは次のとおりです。
<textarea name="somexml">
<Configuration>
<Validator Expression="[^&lt;]" />
<Validator Expression="[^&amp;]" />
</Configuration>
</textarea>
質問は、textarea要素のコンテンツモデルの誤解に基づいています-検証者はすぐに問題を見つけたでしょう。
ETA re comment:さて、どのような問題が残っていますか?それがシリアル化側の問題です。残っているのは、それを解析して戻すことだけです。そのためには、ユーザーが整形式のXMLを作成できると仮定する必要があります。
「<!> lt;」などのエラーを許可するために、整形式でないXMLの解析を試みますまたは「<!> amp;」属性値でエスケープされていないことは、完全にXMLが機能するはずであることに反して、損失です。整形式のXMLを記述することをユーザーに信頼できない場合は、正規表現文字列の単純な改行区切りリストなど、より簡単な非XMLインターフェイスをユーザーに提供します。
おっしゃるように、通常のシリアライザーはすべてをエスケープします。
問題はテキストブロックです。テキストブロックを通過したものはすべて自分で処理する必要があります。
HttpUtility.HtmlEncode()を試すこともできますが、最も簡単な方法は、CDATAセクションのテキストブロックを通過するものをすべて入れることです。
通常、CDATA <!> quot; crutch <!> quot;に依存するのではなく、すべてを適切にエスケープする必要がありますが、組み込みツールを使用してエスケープすることもできます。 <!> quot; hibernated <!> quot;で編集されたものユーザーによる状態、CDATAが行く方法かもしれないと思います。
この前の質問もご覧ください:
XMLのテキストデータをエンコードする最適な方法
更新
別の応答へのコメントに基づいて、コンテンツだけでなくユーザーにマークアップを表示していることに気付きました。 Xmlパーサーはまあまあです。この場合にできる最善のことは、編集されたxmlを受け入れる前に整形式かどうかをチェックすることだと思います。
おそらく、特定の種類のエラー(リンクされた質問のアンパサンドなど)を自動的に修正しようとしますが、.Net xmlパーサーから最初の検証エラーの行番号と列番号を取得し、それを使用してユーザーに間違いは、彼らが受け入れられる何かを与えるまでです。スキーマに対しても検証する場合のボーナスポイント。
TinyMCE のようなものを見ると、リッチテキストのhtmlを編集できます。ボックス。望みどおりに動作するように設定できない場合は、インスピレーションとして使用できます。
注:(私のテストでは)firefoxは、説明したようにテキスト領域でエスケープされません。具体的には、次のコード:
<textarea cols="80" rows="10" id="1"></textarea>
<script>
elem = document.getElementById("1");
elem.value = '\
<Configuration>\n\
<Validator Expression="[^<]" />\n\
</Configuration>\
'
alert(elem.value);
</script>
ユーザーにアラートが表示され、変更されていない:
<Configuration>
<Validator Expression="[^<]" />
</Configuration>
だから、1つの(実行できない?)ソリューションは、ユーザーがfirefoxを使用することです。
質問の2つの部分が明らかになったようです:
1 表示するXMLはエスケープされません。
たとえば、<!> quot; <
<!> quot; <!> quot; <!> lt; <!> quot;としてエスケープされません。しかし、<!> quot; <!> lt; <!> quot; <!> quot; <!> lt; <!> quot;としてエスケープされていない場合、情報は失われ、元に戻すことはできません。
1つの解決策は、すべての<!> quot; &
<!> quot;をエスケープすることです。 <!> quot; &lt;
<!> quot; <!> quot; &
<!> quot;になります。これは、テキストエリアによって<!> quot; \
<!> quot;としてエスケープされません。あなたがそれを読み返すとき、それはそもそもそうだったでしょう。 (textareaが実際に文字列を変更すると仮定していますが、Firefoxは報告されたとおりに動作しないため、これを確認することはできません)
別の解決策(既に考えた)は、カスタムテキスト領域を構築/購入/借用することです(単純な場合は悪くありませんが、すべての編集キー、ctrl-C、ctrl-shift-leftなどがあります)
2 ユーザーがわざわざエスケープする必要がないようにします。
あなたは脱獄中です:
正規表現の置換はほとんど機能します...しかし、ユーザーが(正当に、指定した条件内で)入力する可能性があるときに、どのようにして終了引用符(<!> quot;)を確実に検出できますか:
<Configuration>
<Validator Expression="[^"<]" />
</Configuration>
正規表現構文の観点から見ると、最後の<!> quot;正規表現の一部、またはその終わりです。正規表現構文は通常、次のような明示的なターミネータを使用してこの問題を解決します。
/[^"<]/
ユーザーがこの構文(ターミネータ付き)を使用し、その構文解析プログラムを作成した場合、正規表現がいつ終了したか、したがって次の<!> quot;文字は正規表現の一部ではなく、XMLの一部であるため、どの部分をエスケープする必要があります。私はあなたがこれをすべきだと言っているのではありません!理論的には可能だと言っています。迅速で汚いものとはほど遠い。
BTW:要素内のテキストにも同じ問題が発生します。以下は、指定された条件の範囲内では正当ですが、解析の問題は同じです:
<Configuration>
<Expression></Expression></Expression>
</Configuration>
<!> quot; any text <!> quot;を許可する構文の基本ルール。区切り文字をエスケープする必要がある(<!> quot;または<!> lt;など)ため、終了を認識できます。ほとんどの構文は、利便性/不便さのために、他の多くのものをエスケープします。 ( EDIT エスケープ文字自体をエスケープする必要があります。XMLの場合、<!> quot; \\
<!> quot;であり、リテラルが<!>としてエスケープされる場合quot; <
<!> quot;正規表現の場合、C / unixスタイルの<!> quot; <=> <!> quot;で、リテラルが<!> quot; <=> < !> quot;)。
ネスト構文、そしてあなたはエスケープ地獄にいます。
簡単な解決策の1つは、ユーザーに伝えることです。これはクイックおよびダーティの構成エディターであるため、派手な<!> quot;エスケープする必要はありません<!> quot; mamby-pamby:
- 次に文字とエスケープを一覧表示します テキストエリアへ。例:<!> quot; <!> lt; <!> quot;として <!> quot; <=> <!> quot;。
- XMLの場合 検証し、リストを再度表示します。
振り返ってみると、 bobince は私の前に同じ基本的な答えを与えました。
すべてのテキストの周りにCDATAを挿入すると、(1)ユーザーが手動でエスケープするのを防ぎ、(2)textareaによって自動的にエスケープされなかったテキストを正しく読み戻すことができる別のエスケープメカニズムが得られます。
<Configuration>
<Validator Expression="<![CDATA[ [^<] ]]>" />
</Configuration>
:-)
この特殊文字-<!> quot; <!> lt; <!> quot; -XMLが有効になるように、他の文字に置き換える必要があります。 XMLの特殊文字については、次のリンクを確認してください:
http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
TextBlockコンテンツをデシリアライザーに送信する前にエンコードすることも試してください:
HttpServerUtility utility = new HttpServerUtility();
string encodedText = utility.HtmlEncode(text);
これは本当に私の唯一の選択肢ですか?これは、フレームワークのどこかに解決策があるほど一般的な問題ではありませんか?
private string EscapeAttributes(string configuration)
{
var lt = @"(?<=\w+\s*=\s*""[^""]*)<(?=[^""]*"")";
configuration = Regex.Replace(configuration, lt, "<");
return configuration;
}
(編集:ラウンドトリップの問題を引き起こすため、アンパサンド置換を削除しました)