Jakie są nieprawidłowe znaki w XML

229

Pracuję z niektórymi plikami XML, które przechowują ciągi, takie jak:

<node>This is a string</node>

Niektóre z tych łańcuchów, które mam przechodzących do węzłów będą miały znaków podoba &, #, $itp .:

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

To nie jest ważne z powodu &.

Nie mogę zawinąć tych ciągów w CDATA, ponieważ muszą być takie, jakie są. Próbowałem znaleźć listę znaków, których nie można umieścić w węzłach XML bez posiadania CDATA.

Czy ktoś może skierować mnie w jedną stronę lub dostarczyć listę nielegalnych postaci?

RailsSon
źródło
4
Czy jest jakiś ważny powód, aby nie używać CDATA?
Peter Perháč
1
Tak, przekazuję ciąg do CMS o nazwie Fatwire, a węzeł z danymi nie może znajdować się w CDATA, nie jestem pewien, dlaczego tak działa Fatwire :(
RailsSon
@Peter: Jak mogę używać CDATA w moim przypadku? stackoverflow.com/questions/6906705/…
Radek

Odpowiedzi:

147

Jedyne znaki są nielegalne &, <a >(jak również "czy 'w atrybutach).

Oni uciekł korzystając podmioty XML , w tym przypadku chcesz &amp;za &.

Naprawdę powinieneś jednak użyć narzędzia lub biblioteki, która pisze dla ciebie XML i abstraktuje tego rodzaju rzeczy, abyś nie musiał się tym martwić.

Welbog
źródło
82
Niektóre znaki kontrolne są również niedozwolone. Zobacz moją odpowiedź poniżej.
dolmen
43
W rzeczywistości to nie do końca prawda. Liczba niższych znaków ascii jest również nieprawidłowa. Jeśli spróbujesz zapisać 0x03 do dokumentu Xml, zwykle pojawia się błąd i jeśli uda ci się poprawnie uciec z niego do dokumentu XML, większość przeglądających będzie narzekać na nieprawidłowy znak. Edge case, ale tak się dzieje.
Rick Strahl
16
Ta odpowiedź jest całkowicie błędna. Oto mój wyjątek XML z niedozwolonym znakiem 0x12 „System.Xml.XmlException:”, wartość szesnastkowa 0x12, jest niepoprawnym znakiem ”
George
8
Jest to również niewłaściwe w innym kierunku; oprócz tego, że brakuje każdej nielegalnej postaci, znaki, które twierdzi, że są nielegalne, są całkowicie legalne, aczkolwiek mają szczególne znaczenie w kontekście.
Jon Hanna
6
W XML 1.0 jest wiele nielegalnych znaków. W rzeczywistości nawet użycie encji znakowej dla większości znaków kontrolnych spowoduje błąd podczas analizy.
Thayne
218

OK, oddzielmy pytanie o znaki, które:

  1. nie są w ogóle ważne w żadnym dokumencie XML.
  2. trzeba uciec.

Odpowiedź udzielona przez @dolmen w „ Co to są nieprawidłowe znaki w XML ” jest nadal aktualna, ale musi zostać zaktualizowana zgodnie ze specyfikacją XML 1.1.

1. Niepoprawne znaki

Opisane tutaj znaki to wszystkie znaki, które można wstawić do dokumentu XML.

1.1 W XML 1.0

Globalna lista dozwolonych znaków to:

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

Zasadniczo znaki sterujące i znaki spoza zakresu Unicode są niedozwolone. Oznacza to również, że wywołanie na przykład encji znakowej&#x3; jest zabronione.

1.2 W XML 1.1

Globalna lista dozwolonych znaków to:

[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]

Ta wersja zalecenia XML rozszerzyła dozwolone znaki, więc znaki kontrolne są dozwolone, i uwzględnia nową wersję standardu Unicode, ale te wciąż są niedozwolone: NUL (x00) , xFFFE , xFFFF ...

Jednak stosowanie znaków kontrolnych i niezdefiniowanych znaków Unicode jest odradzane.

Można również zauważyć, że wszystkie parsery nie zawsze uwzględniają to, a dokumenty XML ze znakami kontrolnymi mogą zostać odrzucone.

2. Znaki, które należy uciec (aby uzyskać dobrze sformułowany dokument):

<Musi być uciekł z &lt;jednostki, gdyż przyjmuje się za początek znacznika.

&Musi być uciekł z &amp;jednostki, gdyż przyjmuje się za początek odesłanie podmiot

>Należy uciekł z&gt; jednostki. Nie jest to obowiązkowe - zależy od kontekstu - ale zdecydowanie zaleca się jego uniknięcie.

'Należy uciekł z A&apos; jednostki - Obowiązkowe w atrybutach zdefiniowanych w apostrofach ale zaleca się, aby zawsze przed nim uciec.

"Należy uciekł z &quot;jednostki - Obowiązkowe w atrybutach zdefiniowanych wewnątrz cudzysłowów, ale zaleca się, aby zawsze przed nim uciec.

potam
źródło
171

Lista prawidłowych znaków znajduje się w specyfikacji XML :

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
dolmen
źródło
7
Należy pamiętać, że chociaż są to znaki prawne, & < > " 'należy je unikać w określonych kontekstach.
D.Shawley,
7
„Legalne” w tym kontekście oznacza, że ​​ich ostateczne zdekodowane wartości są legalne, a nie że są legalne w strumieniu. Jak wyżej, niektóre wartości prawne muszą być usuwane w strumieniu.
SilverbackNet
Mam problem polegający na tym, że 0x1c jest niedozwoloną postacią ... Szukam możliwości w Javie, jak tego uniknąć ...
basZero
Miły przegląd, które znaki są prawidłowe, a które nie, można znaleźć tutaj validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel
8
@xamde Ta lista jest ładna, ale pokazuje tylko znaki, których można użyć do uruchomienia elementu XML. Chodzi o to, które znaki są poprawne w pliku XML ogólnie. Są pewne postacie, które nigdzie nie są dozwolone.
Jon Senchyna
59

Jest to kod C #, aby usunąć niepoprawne znaki XML z ciągu i zwrócić nowy prawidłowy ciąg.

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, ""); 
}
mathifonseca
źródło
6
W przypadku języka Java wzorzec wyrażenia regularnego byłby taki sam. Następnie możesz użyć metody o nazwie replaceAll w klasie String, która oczekuje wzorca wyrażenia regularnego jako parametru. Sprawdź to: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca,
2
Mam takie niepoprawne znaki w moim ciągu: SUSITARIMO D & # x5; L DARBO SUTARTIES Ten kod nie usuwa & # x5; Tak więc dokument xml nie uruchamia się.
Dainius Kreivys
Uważam, że nie można po prostu umieścić tego wzorca w konstruktorze wyrażeń regularnych .NET. Nie sądzę, że rozpoznaje \u10000i \u10FFFFjako pojedyncze znaki, ponieważ wymagają one dwóch charinstancji utf-16 , i zgodnie z dokumentacją może być nie więcej niż 4 cyfry. [\u10000-\u10FFFF]najprawdopodobniej jest analizowany jako [ \u1000, 0-\u10FF, F, F], co jest dziwne, patrząc jednak legalne.
GSerg
17

Wstępnie zadeklarowane postacie to:

& < > " '

Aby uzyskać więcej informacji, zobacz „ Jakie są znaki specjalne w XML? ”.

cgp
źródło
Źle. Nie wszystkie są nieprawidłowe. Tylko & i <są zawsze nieprawidłowe w tekście.
rghome
7

Oprócz odpowiedzi potame, jeśli chcesz uciec za pomocą bloku CDATA.

Jeśli umieścisz tekst w bloku CDATA, nie musisz używać klawisza zmiany znaczenia . W takim przypadku możesz użyć wszystkich znaków z następującego zakresu :

graficzna reprezentacja możliwych znaków

Uwaga: Ponadto nie możesz używać ]]>sekwencji znaków. Ponieważ pasowałby do końca bloku CDATA.

Jeśli nadal występują nieprawidłowe znaki (np. Znaki kontrolne), prawdopodobnie lepiej jest użyć pewnego rodzaju kodowania (np. Base64).

bvdb
źródło
3
Bez względu na blok CDATA, niektóre znaki są zabronione w XML.
dolmen
4
dokładnie, czy nie to napisałem? cytat: „wszystkie znaki z następującego zakresu ”. Rozumiem przez to tylko postacie z tego konkretnego zakresu. Inne postacie są niedozwolone. - w pełni się zgadzam ; ale nie rozumiem opinii. - ale żadnych trudnych uczuć.
bvdb
6

Innym łatwym sposobem na uniknięcie potencjalnie niechcianych znaków XML / XHTML w C #:

WebUtility.HtmlEncode(stringWithStrangeChars)
tygi
źródło
Nieprawidłowe postacie
dolmen
1
Napisał Xml, a nie HTML.
Emanuele
6

Innym sposobem na usunięcie niepoprawnych znaków XML w języku C # XmlConvert.IsXmlChar(dostępne od .NET Framework 4.0)

public static string RemoveInvalidXmlChars(string content)
{
   return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());
}

lub możesz sprawdzić, czy wszystkie znaki są poprawne XML:

public static bool CheckValidXmlChars(string content)
{
   return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));
}

.Net Fiddle

Na przykład pionowy symbol tabulacji ( \v) nie jest poprawny dla XML, jest poprawny UTF-8, ale nie jest poprawny XML 1.0, a nawet wielu bibliotekom (w tym libxml2) brakuje go i cicho wyprowadza nieprawidłowy XML.

Alex Vazhev
źródło
2

Podsumowując, prawidłowe znaki w tekście to:

  • tab, podawanie wiersza i powrót karetki.
  • wszystkie znaki niekontrolujące są poprawne, z wyjątkiem & i< .
  • >nie jest ważny, jeśli następuje ]].

Sekcje 2.2 i 2.4 specyfikacji XML zawierają szczegółową odpowiedź:

Postacie

Prawnymi znakami są tabulator, znak powrotu karetki, przesunięcie wiersza oraz prawne znaki Unicode i ISO / IEC 10646

Dane postaci

Znak ampersand (&) i lewy nawias kątowy (<) nie mogą występować w postaci dosłownej, z wyjątkiem przypadków, gdy są używane jako ograniczniki znaczników lub w komentarzu, instrukcji przetwarzania lub sekcji CDATA. Jeśli są potrzebne gdzie indziej, należy je uciec za pomocą odwołań do znaków numerycznych lub odpowiednio ciągów znaków „&” i „<”. Nawias prostokątny (>) może być reprezentowany za pomocą ciągu „>” i, dla kompatybilności, musi być poprzedzony znakiem „>” lub odwołaniem do znaku, gdy pojawia się w ciągu „]]>„ w treści, gdy to ciąg nie oznacza końca sekcji CDATA.

rghome
źródło
2

XmlWriter i niższe znaki ASCII ” działały dla mnie

string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");
Kalpesh Popat
źródło
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;

W języku C # użyj System.Security.SecurityElement.Escapelub, System.Net.WebUtility.HtmlEncodeaby uciec przed tymi nielegalnymi postaciami.

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;"
żywa miłość
źródło
1

Dla ludzi Javy Apache ma klasę narzędziową ( StringEscapeUtils), która ma metodę pomocniczą, escapeXmlktórej można użyć do zmiany znaczenia znaków w ciągu za pomocą encji XML.

Wskaźnik zerowy
źródło
1

W procesorze XML Woodstox nieprawidłowe znaki są klasyfikowane według tego kodu:

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

Źródło stąd

Jerome Saint-Yves
źródło
-1

Ktoś tego próbował System.Security.SecurityElement.Escape(yourstring)? Spowoduje to zastąpienie niepoprawnych znaków XML w łańcuchu ich prawidłowym odpowiednikiem.

klaydze
źródło
-5

Do XSL (w naprawdę leniwe dni) używam:

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

tłumaczyć wszystkie znaki, które nie są obserwowane na stronie; do właściwych.

Mamy przypadki, w których dane wejściowe są w formacie CDATA, ale system, który używa XML, nie bierze tego pod uwagę. To niechlujna poprawka, uważaj ...

Samson Wiklund
źródło
8
Jeśli jest niechlujny, czy naprawdę konieczne jest opublikowanie go tutaj?
dolmen,