Zastanawiałem się, czy istnieje sposób na uniknięcie tokena końcowego CDATA ( ]]>
) w sekcji CDATA w dokumencie xml. Lub, bardziej ogólnie, jeśli istnieje jakaś sekwencja ucieczki do użycia w CDATA (ale jeśli istnieje, myślę, że prawdopodobnie i tak miałaby sens tylko ucieczka od tokenów początku lub końca).
Zasadniczo, czy możesz mieć token początku lub końca osadzony w CDATA i powiedzieć parserowi, aby go nie interpretował, ale traktował jako kolejną sekwencję znaków.
Prawdopodobnie powinieneś po prostu refaktoryzować swoją strukturę xml lub kod, jeśli próbujesz to zrobić, ale mimo że pracuję z xml na co dzień przez ostatnie 3 lata i nigdy nie miałem tego problemu, Zastanawiałem się, czy to możliwe. Z czystej ciekawości.
Edytować:
Poza kodowaniem html ...
>
jak>
w przypadku CData, aby zapewnić, że elementy osadzone]]>
nie zostaną przeanalizowane jako CDEnd. Oznacza to po prostu, że jest to nieoczekiwane i&
musi NAJPIERW zostać zakodowane,&
aby dane mogły zostać prawidłowo zdekodowane. Użytkownicy dokumentu muszą wiedzieć, aby zdekodować również te dane CD. Nie jest to niespotykane, ponieważ częścią CData jest przechowywanie treści, z którymi określony konsument rozumie, jak sobie z nimi radzić. Po prostu nie można oczekiwać, że taka CData będzie właściwie interpretowana przez żadnego ogólnego konsumenta.CDATA
został zaprojektowany tak, aby zezwalać na wszystko : są one używane do zmiany znaczenia bloków tekstu zawierających znaki, które w przeciwnym razie zostałyby rozpoznane jako znaczniki. ToCDATA
również sugeruje, ponieważ jest to również znacznik. Ale w rzeczywistości nie potrzebujesz podwójnego kodowania, które zasugerowałem.]]>
jest dopuszczalnym sposobem kodowania aCDEnd
wCDATA
.Odpowiedzi:
Oczywiście to pytanie jest czysto akademickie. Na szczęście ma bardzo określoną odpowiedź.
Nie można uciec przed sekwencją końcową CDATA. Reguła produkcji 20 specyfikacji XML jest dość jasna:
EDYCJA: Ta reguła iloczynu dosłownie oznacza „Sekcja CData może zawierać wszystko, co chcesz, ALE sekwencja ']]>'. Bez wyjątku.”.
EDYCJA2: ta sama sekcja czyta również:
Innymi słowy, nie jest możliwe użycie odwołania do encji, znaczników ani żadnej innej formy interpretowanej składni. Jedyny przeanalizowany tekst w sekcji CDATA to
]]>
i kończy sekcję.Dlatego nie można uciec
]]>
z sekcji CDATA.EDYCJA3: ta sama sekcja czyta również:
Wtedy może istnieć sekcja CDATA wszędzie tam, gdzie mogą wystąpić dane znakowe, w tym wiele sąsiednich sekcji CDATA zamiast jednej sekcji CDATA. Dzięki temu możliwe jest podzielenie
]]>
tokena i umieszczenie jego dwóch części w sąsiednich sekcjach CDATA.dawny:
<![CDATA[Certain tokens like ]]> can be difficult and <invalid>]]>
należy zapisać jako
źródło
<script>/*<![CDATA[*/javascript goes here/*]]>*/</script>
a mój javascript zawiera tylko tę sekwencję! Podoba mi się pomysł podziału na wiele sekcji CDATA ...[[United States dollar|US$]]>100 million (2013)
który został przetłumaczony[[United States dollar|US$]]>100 million (2013)
przez czytelnika, a autor zdecydował się na użycie CDATA w celu uniknięcia tekstu, ale nie powiodło się.Musisz rozbić swoje dane na części, aby ukryć
]]>
.Oto cała sprawa:
<![CDATA[]]]]><![CDATA[>]]>
Pierwsza
<![CDATA[]]]]>
ma]]
. Drugi<![CDATA[>]]>
ma>
.źródło
]]>
jako]]]]><![CDATA[>
. 5 razy dłuższa ... wow. Ale jest to niecodzienna sekwencja.Nie uciec
]]>
, ale można uciec>
po]]
wstawiając]]><![CDATA[
przed>
, myśleć o tym po prostu jak\
w C / Java / PHP / Perl ciąg ale potrzebne tylko przed>
i po]]
.BTW,
Odpowiedź S. Lotta jest taka sama, tylko inaczej sformułowana.
źródło
]]]]><![CDATA[>
to nie jest jakaś magiczna sekwencja]]>
.]]]]>
zawiera]]
znaki jako dane i]]>
kończy bieżącą sekcję CDATA.<![CDATA[>
uruchamia nową sekcję CDATA i umieszcza>
w niej. W rzeczywistości są to dwa różne elementy i będą traktowane inaczej podczas pracy z parserem DOM. Powinieneś być tego świadomy. Ten sposób jest podobny do tego]]]><![CDATA[]>
, z wyjątkiem tego, że umieszcza]
w pierwszym i]>
drugim CDATA. Różnica pozostaje.Odpowiedź S. Lotta jest prawidłowa: nie kodujesz znacznika końcowego, dzielisz go na wiele sekcji CDATA.
Jak rozwiązać ten problem w prawdziwym świecie: używając edytora XML do stworzenia dokumentu XML, który zostanie wprowadzony do systemu zarządzania treścią, spróbuj napisać artykuł o sekcjach CDATA. Twoja zwykła sztuczka polegająca na osadzaniu próbek kodu w sekcji CDATA zawiedzie Cię tutaj. Możesz sobie wyobrazić, jak się tego nauczyłem.
Ale w większości przypadków nie napotkasz tego, a oto dlaczego: jeśli chcesz przechowywać (powiedzmy) tekst dokumentu XML jako zawartość elementu XML, prawdopodobnie użyjesz metody DOM, np:
XmlElement elm = doc.CreateElement("foo"); elm.InnerText = "<[CDATA[[Is this a problem?]]>";
A DOM całkiem rozsądnie wymyka się znakom <i>, co oznacza, że nieumyślnie nie osadziłeś sekcji CDATA w swoim dokumencie.
Aha, i to jest interesujące:
XmlDocument doc = new XmlDocument(); XmlElement elm = doc.CreateElement("doc"); doc.AppendChild(elm); string data = "<![[CDATA[This is an embedded CDATA section]]>"; XmlCDataSection cdata = doc.CreateCDataSection(data); elm.AppendChild(cdata);
Jest to prawdopodobnie przypadek ideologii .NET DOM, ale nie stanowi to wyjątku. Wyjątek zostanie zgłoszony tutaj:
Domyślam się, że to, co dzieje się pod maską, polega na tym, że XmlDocument używa XmlWriter do tworzenia swoich danych wyjściowych, a XmlWriter sprawdza, czy podczas pisania jest poprawna.
źródło
po prostu zastąpić
]]>
z]]]]><![CDATA[>
źródło
Oto kolejny przypadek, w którym
]]>
należy uciec. Załóżmy, że musimy zapisać doskonale poprawny dokument HTML wewnątrz bloku CDATA dokumentu XML, a tak się składa, że źródło HTML ma swój własny blok CDATA. Na przykład:<htmlSource><![CDATA[ ... html ... <script type="text/javascript"> /* <![CDATA[ */ -- some working javascript -- /* ]]> */ </script> ... html ... ]]></htmlSource>
skomentowany sufiks CDATA należy zmienić na:
ponieważ parser XML nie będzie wiedział, jak obsługiwać bloki komentarzy javascript
źródło
]]>
ze]]]]><![CDATA[>
nadal obowiązuje tutaj. Fakt, że jest to JavaScript lub skomentowany, nie jest ważny.W PHP:
'<![CDATA['.implode(explode(']]>', $string), ']]]]><![CDATA[>').']]>'
źródło
Czystszy sposób w PHP:
Nie zapomnij użyć wielobajtowego bezpiecznego str_replace, jeśli jest to wymagane (inne niż latin1
$string
):źródło
Nie sądzę, aby przerywanie CDATA było dobrym rozwiązaniem. Oto moja alternatywa ...
Użyj
]
dla sekwencji ucieczki, po której następuje wartość szesnastkowa twojej postaci. Jak w&#xhhhh;
=>]<unicode value>;
W ten sposób, jeśli spróbujesz nagrać
]]>
swoje kodowanie, fn da,]005D;]005D;]003E;
co jest w porządku w CDATA.Jest to lepsze niż ucieczka przez nazwę jednostki, ponieważ nie są one dekodowane za każdym razem w aplikacji i możesz mieć inne priorytety ucieczki jednostek za pomocą znaku ampersand i ucieczki przed niektórymi innymi znakami / sekwencjami. W rezultacie masz większą kontrolę nad zawartością CDATA.
źródło
Zobacz tę strukturę:
W przypadku wewnętrznych znaczników CDATA należy zamknąć za pomocą
]]]]><![CDATA[>
zamiast]]>
. Proste.źródło