私は現在いくつかのXMLを扱っています。
以下のような文字列を保持するノードがあります。
<node>This is a string</node>
私がノードに渡している文字列の中には、&、#、$などの文字が含まれているものがあります。
<node>This is a string & so is this</node>
&のため、これは無効です。
これらの文字列をCDATAでラップすることはできません。 CDATAに含まれていないとXMLノードに入れることができない文字のリストをオンラインで探してみました。
誰かが私を1の方向に向けたり、違法な文字のリストを私に提供したりできますか?
唯一の不正な文字は、&
、<
、および>
(および属性の"
または'
)です。
これらは XMLエンティティ を使用してエスケープされます。この場合は&
に&
が必要です。
しかし、実際には、XMLを記述し、このようなことを抽象化するツールやライブラリを使用する必要があります。そのため、心配する必要はありません。
それでは、(1)どのXML文書でもまったく無効な文字と、(2)エスケープする必要がある文字の質問を分けてみましょう。
@dolmen XMLの無効文字 によって提供される回答はまだ有効ですが、XML 1.1仕様に従って更新する必要があります。
ここで説明されている文字は、XML文書に挿入できるすべての文字です。
許可される文字のグローバルリストは次のとおりです。
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
基本的に、制御文字およびUnicode範囲外の文字は許可されていません。これは、例えば文字実体
の呼び出しが禁止されていることも意味します。
許可される文字のグローバルリストは次のとおりです。
[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]
このXML勧告の改訂では、制御文字が許可されるように許可文字を拡張し、Unicode標準の新しい改訂を考慮に入れていますが、これらはまだ許可されていません。NUL(x00)、xFFFE、xFFFF...
ただし、制御文字と未定義のUnicode文字の使用はお勧めできません。
また、すべてのパーサーが必ずしもこれを考慮に入れるわけではなく、制御文字を含むXML文書が拒否される可能性があることにも気付くことができます。
<
はタグの先頭と見なされるため、<
エンティティでエスケープする必要があります。
&
はエンティティ参照の始まりであると見なされるため、&
エンティティでエスケープする必要があります。
>
は>
エンティティでエスケープする必要があります。それは必須ではありません - それは文脈によります - しかしそれを避けることを強く勧めます。
'
は'
エンティティでエスケープする必要があります - 単一引用符で囲まれた属性では必須ですが、常にそれをエスケープすることを強くお勧めします。
"
は"
エンティティでエスケープする必要があります - 二重引用符で囲まれた属性では必須ですが、常にエスケープすることを強くお勧めします。
有効な文字のリストは、 XML仕様 にあります。
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
これは、文字列からXMLの無効な文字を削除し、新しい有効な文字列を返すためのC#コードです。
public static string CleanInvalidXmlChars(string text)
{
// From xml spec valid chars:
// #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
// any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
string re = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]";
return Regex.Replace(text, re, "");
}
C#で不要と思われるXML/XHTML文字を回避するためのもう1つの簡単な方法は、次のとおりです。
WebUtility.HtmlEncode(stringWithStrangeChars)
XmlConvert.IsXmlCharメソッド を使用して、C#で誤ったXML文字を削除する別の方法(.NET Framework 4.0以降で使用可能)
public static string RemoveInvalidXmlChars(string content)
{
return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());
}
または、すべての文字がXMLに有効であることを確認することもできます。
public static bool CheckValidXmlChars(string content)
{
return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));
}
.Net Fiddle - https://dotnetfiddle.net/v1TNus
たとえば、垂直タブ記号(\ v)はXMLには無効で、UTF-8には有効ですがXML 1.0には無効で、多くのライブラリ(libxml2を含む)でさえそれを見逃し、黙って無効なXMLを出力します。
この答えは私のために働きました
string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");
ブログへのこの リンクの詳細
ampersand (&) is escaped to &
double quotes (") are escaped to "
single quotes (') are escaped to '
less than (<) is escaped to <
greater than (>) is escaped to >
C#では、System.Security.SecurityElement.EscapeまたはSystem.Net.WebUtility.HtmlEncodeを使用してこれらの不正な文字をエスケープします。
string xml = "<node>it's my \"node\" & i like it 0x12 x09 x0A 0x09 0x0A <node>";
string encodedXml1 = System.Security.SecurityElement.Escape(xml);
string encodedXml2= System.Net.WebUtility.HtmlEncode(xml);
encodedXml1
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
encodedXml2
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
Woodstox XMLプロセッサーでは、無効な文字はこのコードで分類されます
if (c == 0) {
throw new IOException("Invalid null character in text to output");
}
if (c < ' ' || (c >= 0x7F && c <= 0x9F)) {
String msg = "Invalid white space character (0x" + Integer.toHexString(c) + ") in text to output";
if (mXml11) {
msg += " (can only be output using character entity)";
}
throw new IOException(msg);
}
if (c > 0x10FFFF) {
throw new IOException("Illegal unicode character point (0x" + Integer.toHexString(c) + ") to output; max is 0x10FFFF as per RFC");
}
/*
* Surrogate pair in non-quotable (not text or attribute value) content, and non-unicode encoding (ISO-8859-x,
* Ascii)?
*/
if (c >= SURR1_FIRST && c <= SURR2_LAST) {
throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content");
}
throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output");
Javaの人々のために、Apacheは、XMLエンティティを使用して文字列内の文字をエスケープするために使用できるヘルパーメソッドescapeXmlを持つユーティリティクラス(StringEscapeUtils)を持っています。
要約すると、テキスト内の有効な文字は次のとおりです。
XML仕様のセクション2.2および2.4に詳細な回答があります。
文字
有効な文字は、タブ、キャリッジリターン、ラインフィード、およびUnicodeとISO/IEC 10646の有効な文字です。
文字データ
アンパサンド文字(&)および左角かっこ(<)は、マークアップ区切り文字として使用される場合、またはコメント、処理命令、またはCDATAセクション内で使用される場合を除き、リテラル形式で表示されてはなりません。それらが他の場所で必要とされる場合、それらはそれぞれ数字参照か文字列 "&"と "<"のどちらかを使用してエスケープされなければなりません。直角括弧(>)は文字列 ">"を使用して表すことができ、互換性のために、文字列 "]]>"内に現れる場合は ">"または文字参照を使用してエスケープする必要があります。 stringはCDATAセクションの終わりを示していません。
誰もがこのSystem.Security.SecurityElement.Escape(yourstring)
を試しましたか?これは、文字列内の無効なXML文字をそれらの有効な等価物と置き換えます。