XML에서 유효하지 않은 문자


229

다음과 같은 문자열을 보유한 일부 XML로 작업하고 있습니다.

<node>This is a string</node>

내가 노드에 전달하고있는 문자열 중 일부는 것입니다 문자처럼 &, #, $, 등 :

<node>This is a string & so is this</node>

로 인해 유효하지 않습니다 &.

이 문자열을 그대로 그대로 CDATA에 래핑 할 수 없습니다. CDATA에 있지 않고 XML 노드에 넣을 수없는 문자 목록을 찾으려고했습니다.

누군가 나를 지시하거나 불법적 인 인물 목록을 제공 할 수 있습니까?


4
CDATA를 사용하지 않는 유효한 이유가 있습니까?
Peter Perháč

1
예, 문자열을 Fatwire라는 CMS로 전달하고 있는데 데이터가있는 노드는 CDATA에있을 수 없습니다. Fatwire가 작동하는 방식이 확실하지 않습니다. (
RailsSon

@ 피터 : 내 경우에 CDATA를 어떻게 사용할 수 있습니까? stackoverflow.com/questions/6906705/…
Radek

답변:


147

유일한 불법 문자는 &, <그리고 >(물론 "'속성에서).

그들은를 빠져있는 XML 엔티티를 원하는이 경우, &amp;위해 &.

그러나 실제로 XML을 작성하고 이러한 종류의 내용을 추상화하는 도구 또는 라이브러리를 사용해야하므로 걱정할 필요가 없습니다.


82
일부 제어 문자도 허용되지 않습니다. 아래 답변을 참조하십시오.
고인돌

43
사실 그것은 사실이 아닙니다. 여러 하위 ASCII 문자도 유효하지 않습니다. Xml 문서에 0x03을 쓰려고 시도하면 일반적으로 오류가 발생하고 XML 문서로 올바르게 이스케이프 처리하지 않으면 대부분의 뷰어가 잘못된 문자에 대해 불평합니다. 가장자리 경우이지만 발생합니다.
Rick Strahl

16
이 답변은 절대적으로 잘못되었습니다. 다음은 0x12 잘못된 문자 'System.Xml.XmlException이있는 XML 예외입니다.' ', 16 진수 값 0x12는 잘못된 문자입니다'
George

8
다른 방향으로도 잘못되었습니다. 불법적 인 성격을 가진 모든 인물을 잃어 버릴뿐만 아니라, 불법이라고 주장하는 인물은 문맥 상 특별한 의미를 갖지만 완벽하게 합법적입니다.
Jon Hanna

6
XML 1.0에는 많은 잘못된 문자가 있습니다. 실제로 대부분의 제어 문자에 문자 엔티티를 사용하더라도 구문 분석시 오류가 발생합니다.
Thayne

218

자, 다음과 같은 문자에 대한 질문을 분리합시다.

  1. XML 문서에서 전혀 유효하지 않습니다.
  2. 탈출해야합니다.

@dolmen이 " XML의 유효하지 않은 문자 란 무엇입니까? "에서 제공 한 답변 은 여전히 ​​유효하지만 XML 1.1 사양으로 업데이트해야합니다.

1. 잘못된 문자

여기에 설명 된 문자는 XML 문서에 삽입 할 수있는 모든 문자입니다.

1.1. XML 1.0에서

허용되는 문자의 전체 목록은 다음과 같습니다.

[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

기본적으로 제어 문자 및 유니 코드 범위를 벗어난 문자는 허용되지 않습니다. 이것은 또한 예를 들어 캐릭터 엔티티의 호출 &#x3;이 금지됨을 의미합니다.

1.2. XML 1.1에서

허용되는 문자의 전체 목록은 다음과 같습니다.

[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 권장 사항의이 개정은 허용 문자를 확장하여 제어 문자가 허용되며 유니 코드 표준의 새로운 개정을 고려하지만 NUL (x00) , xFFFE , xFFFF ...

그러나 제어 문자 및 정의되지 않은 유니 코드 문자를 사용하지 않는 것이 좋습니다.

모든 파서가이를 항상 고려하지는 않으며 제어 문자가있는 XML 문서는 거부 될 수 있습니다.

2. 제대로 구성된 문서를 얻기 위해 이스케이프해야하는 문자 :

<로 이스케이프해야 &lt;이 태그의 시작으로 간주되기 때문에, 엔티티.

&로 이스케이프해야합니다 &amp;시작하는 엔티티 참조로 간주되기 때문에, 엔티티

>로 이스케이프해야합니다 &gt;엔티티. 필수는 아니며 상황에 따라 다르지만 탈출하는 것이 좋습니다.

'로 이스케이프해야 &apos;엔티티 - 작은 따옴표 내에 정의 된 속성에 필수 있지만 강력 항상 탈출하는 것이 좋습니다.

"로 이스케이프해야 &quot;엔티티 - 따옴표로 정의 된 속성에 필수 있지만 강력 항상 탈출하는 것이 좋습니다.


171

유효한 문자 목록은 XML 사양에 있습니다 .

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

7
그것들은 합법적 인 성격이지만 & < > " '특정 상황에서는 탈출해야합니다.
D.Shawley

7
이러한 맥락에서 "법적"은 최종 디코딩 된 값이 합법적이며 스트림에서 합법적이지 않다는 것을 의미합니다. 위와 같이 일부 법적 가치는 인스 트림에서 벗어나야합니다.
SilverbackNet

0x1c가 잘못된 문자 인 경우에 문제가 있습니다. Java에서 이러한 문제를 피하는 방법을 찾고 있습니다 ....
basZero

문자가 유효하고 좋은 개요는 여기에서 찾을 수 있습니다되지 않습니다 validchar.com/d/xml10/xml10_namestart
박사 최대 Völkel을

8
@xamde이 목록은 훌륭하지만 XML 요소를 시작하는 데 사용할 수있는 문자 만 표시합니다. 당면한 문제는 일반적으로 XML 파일에서 어떤 문자가 유효한지입니다. 어디에도 허용되지 않는 특정 문자가 있습니다.
Jon Senchyna 2016 년

59

문자열에서 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, ""); 
}

6
Java의 경우 정규식 패턴은 동일합니다. 그런 다음 정규식 패턴을 매개 변수로 사용하는 String 클래스에서 replaceAll이라는 메서드를 사용할 수 있습니다. 이것을 확인하십시오 : docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca

2
문자열에 잘못된 문자가 있습니다. SUSITARIMO D & # x5; L DARBO SUTARTIES이 코드는 & # x5; 따라서 xml 문서가 초기화되지 않습니다.
Dainius Kreivys

이 패턴을 .NET 정규식 생성자에 넣을 수는 없다고 생각합니다. 나는 두 개의 utf-16 인스턴스가 필요 하기 때문에 인식 \u10000하고 \u10FFFF단일 문자로 생각하지 않으며 문서char 에 따르면 4 자릿수가 넘지 않을 수 있습니다. 가장 가능성으로 해석된다 , , , ]보고 이상한하지만 법적이다. [\u10000-\u10FFFF]\u10000-\u10FFFF
GSerg


7

CDATA 블록을 사용하여 탈출하려는 경우 potame의 답변 외에도.

텍스트 를 CDATA 블록에 넣으면 escaping을 사용할 필요가 없습니다 . 이 경우 다음 범위의 모든 문자를 사용할 수 있습니다 .

가능한 문자의 그래픽 표현

참고 : 그 외에도 ]]>문자 시퀀스 를 사용할 수 없습니다 . CDATA 블록의 끝과 일치하기 때문입니다.

여전히 유효하지 않은 문자 (예 : 제어 문자)가있는 경우 일종의 인코딩 (예 : base64)을 사용하는 것이 좋습니다.


3
CDATA 블록이든 아니든 일부 문자는 XML에서 금지되어 있습니다.
고인돌

4
정확히 내가 쓴 것이 아닙니까? 인용 : " 다음 범위의 모든 문자 ". 즉,이 특정 범위의 문자 만 의미합니다. 다른 문자는 허용되지 않습니다. - 전적으로 동의 ; 그러나 나는 공감대를 이해하지 못한다. -어려운 감정은 없습니다.
bvdb

6

C #에서 잠재적으로 원하지 않는 XML / XHTML 문자를 피하는 또 다른 쉬운 방법은 다음과 같습니다.

WebUtility.HtmlEncode(stringWithStrangeChars)

잘못된 문자
고인돌

1
그는 HTML이 아닌 Xml을 썼습니다.
Emanuele

6

C #에서 잘못된 XML 문자를 제거하는 또 다른 방법은 XmlConvert.IsXmlChar(.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 피들

예를 들어, 세로 탭 기호 ( \v)는 XML에는 유효하지 않으며 UTF-8에는 유효하지만 유효한 XML 1.0에는 유효하지 않으며 많은 라이브러리 (libxml2 포함)에서도이를 누락하고 자동으로 잘못된 XML을 출력합니다.


2

요약하면 텍스트에서 유효한 문자는 다음과 같습니다.

  • 탭, 줄 바꿈 및 캐리지 리턴.
  • 이외의 모든 제어 문자는 유효 을 제외 & 하고 <.
  • >다음과 같은 경우에는 유효하지 않습니다 ]].

XML 사양의 섹션 2.2와 2.4는 자세한 답변을 제공합니다.

캐릭터

유효한 문자는 탭, 캐리지 리턴, 줄 바꿈 및 유효한 문자 및 유니 코드 및 ISO / IEC 10646입니다.

캐릭터 데이터

앰퍼샌드 문자 (&) 및 왼쪽 꺾쇠 괄호 (<)는 마크 업 구분 기호로 사용되거나 주석, 처리 명령 또는 CDATA 섹션 내에서 사용되는 경우를 제외하고 리터럴 형식으로 표시되어서는 안됩니다. 다른 곳에서 필요한 경우 숫자 참조 나 문자열 "&"및 "<"를 사용하여 이스케이프해야합니다. 직각 괄호 (>)는 문자열 ">"을 사용하여 표현할 수 있으며, 호환성을 위해 ">"또는 문자열 "]]>"에 문자 참조가 표시 될 때 문자 참조를 사용하여 이스케이프해야합니다. 문자열이 CDATA 섹션의 끝을 표시하지 않습니다.



1
ampersand (&) is escaped to &amp;

double quotes (") are escaped to &quot;

single quotes (') are escaped to &apos; 

less than (<) is escaped to &lt; 

greater than (>) is escaped to &gt;

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
"&lt;node&gt;it&apos;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

encodedXml2
"&lt;node&gt;it&#39;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

1

Java 사용자를 위해 Apache에는 XML 엔티티를 사용하여 문자열에서 문자를 이스케이프하는 데 사용할 수 StringEscapeUtils있는 도우미 메소드 가있는 유틸리티 클래스 ( )가 있습니다 escapeXml.


1

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");

여기 에서 소스


-1

아무도 이것을 시도 System.Security.SecurityElement.Escape(yourstring)? 이것은 문자열에서 유효하지 않은 XML 문자를 유효한 문자로 바꿉니다.


-5

XSL (실제로 게으른 날)의 경우 다음을 사용합니다.

capture="&amp;(?!amp;)" capturereplace="&amp;amp;"

다음과 같이 모든 앰프를 번역하지 않습니다. 적절한 사람에게.

입력이 CDATA에 있지만 XML을 사용하는 시스템이 입력을 고려하지 않는 경우가 있습니다. 조잡한 수정이므로 조심하십시오 ...


8
엉성한 경우 여기에 게시해야합니까?
dolmen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.