Bardzo podobne do tego pytania , z wyjątkiem Javy.
Jaki jest zalecany sposób kodowania ciągów znaków wyjściowych XML w języku Java. Ciągi mogą zawierać znaki takie jak „&”, „<” itp.
Bardzo podobne do tego pytania , z wyjątkiem Javy.
Jaki jest zalecany sposób kodowania ciągów znaków wyjściowych XML w języku Java. Ciągi mogą zawierać znaki takie jak „&”, „<” itp.
Bardzo prosto: użyj biblioteki XML. W ten sposób faktycznie będzie to właściwe, zamiast wymagać szczegółowej znajomości bitów specyfikacji XML.
Jak wspominali inni, użycie biblioteki XML jest najłatwiejszym sposobem. Jeśli chcesz uciec samemu, można spojrzeć
StringEscapeUtils
z Apache Commons Lang bibliotece.źródło
StringEscapeUtils.escapeXml(str)
zcommons-lang
. Używam go w aplikacji App Engine - działa jak marzenie. Oto dokument Java dla tej funkcji:\t
,\n
i\r
.\t
,\n
czy\r
trzeba uciekać?Po prostu użyj.
Pozwoli to na dowolne znaki z wyjątkiem zakończenia
]]>
Możesz więc dołączyć znaki, które byłyby nielegalne, takie jak & i>. Na przykład.
<element><![CDATA[ characters such as & and > are allowed ]]></element>
Jednak atrybuty będą musiały być chronione, ponieważ nie można do nich używać bloków CDATA.
źródło
Pomogło mi to, udostępniając wersję ciągu tekstowego z ucieczką:
public class XMLHelper { /** * Returns the string where all non-ascii and <, &, > are encoded as numeric entities. I.e. "<A & B >" * .... (insert result here). The result is safe to include anywhere in a text field in an XML-string. If there was * no characters to protect, the original string is returned. * * @param originalUnprotectedString * original string which may contain characters either reserved in XML or with different representation * in different encodings (like 8859-1 and UFT-8) * @return */ public static String protectSpecialCharacters(String originalUnprotectedString) { if (originalUnprotectedString == null) { return null; } boolean anyCharactersProtected = false; StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < originalUnprotectedString.length(); i++) { char ch = originalUnprotectedString.charAt(i); boolean controlCharacter = ch < 32; boolean unicodeButNotAscii = ch > 126; boolean characterWithSpecialMeaningInXML = ch == '<' || ch == '&' || ch == '>'; if (characterWithSpecialMeaningInXML || unicodeButNotAscii || controlCharacter) { stringBuffer.append("&#" + (int) ch + ";"); anyCharactersProtected = true; } else { stringBuffer.append(ch); } } if (anyCharactersProtected == false) { return originalUnprotectedString; } return stringBuffer.toString(); } }
źródło
Spróbuj tego:
String xmlEscapeText(String t) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < t.length(); i++){ char c = t.charAt(i); switch(c){ case '<': sb.append("<"); break; case '>': sb.append(">"); break; case '\"': sb.append("""); break; case '&': sb.append("&"); break; case '\'': sb.append("'"); break; default: if(c>0x7e) { sb.append("&#"+((int)c)+";"); }else sb.append(c); } } return sb.toString(); }
źródło
t==null
.To pytanie ma już osiem lat i nadal nie jest w pełni poprawną odpowiedzią! Nie, nie musisz importować całego interfejsu API innej firmy, aby wykonać to proste zadanie. Zła rada.
Następująca metoda:
Próbowałem zoptymalizować pod kątem najczęstszego przypadku, jednocześnie zapewniając, że możesz przez to potokować / dev / random i uzyskać prawidłowy ciąg w XML.
public static String encodeXML(CharSequence s) { StringBuilder sb = new StringBuilder(); int len = s.length(); for (int i=0;i<len;i++) { int c = s.charAt(i); if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) { c = ((c-0xd7c0)<<10) | (s.charAt(++i)&0x3ff); // UTF16 decode } if (c < 0x80) { // ASCII range: test most common case first if (c < 0x20 && (c != '\t' && c != '\r' && c != '\n')) { // Illegal XML character, even encoded. Skip or substitute sb.append("�"); // Unicode replacement character } else { switch(c) { case '&': sb.append("&"); break; case '>': sb.append(">"); break; case '<': sb.append("<"); break; // Uncomment next two if encoding for an XML attribute // case '\'' sb.append("'"); break; // case '\"' sb.append("""); break; // Uncomment next three if you prefer, but not required // case '\n' sb.append(" "); break; // case '\r' sb.append(" "); break; // case '\t' sb.append("	"); break; default: sb.append((char)c); } } } else if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) { // Illegal XML character, even encoded. Skip or substitute sb.append("�"); // Unicode replacement character } else { sb.append("&#x"); sb.append(Integer.toHexString(c)); sb.append(';'); } } return sb.toString(); }
Edycja: dla tych, którzy nadal upierają się, że pisanie własnego kodu do tego celu jest głupie, gdy istnieją doskonale dobre API Java do obsługi XML, możesz chcieć wiedzieć, że StAX API zawarte w Oracle Java 8 (nie testowałem innych ) nie koduje poprawnie zawartości CDATA: nie zmienia sekwencji]]> w treści. Biblioteka innej firmy, nawet taka, która jest częścią rdzenia Java, nie zawsze jest najlepszą opcją.
źródło
StringEscapeUtils.escapeXml()
nie zmienia znaczenia znaków kontrolnych (<0x20). XML 1.1 umożliwia stosowanie znaków sterujących; XML 1.0 nie. Na przykład,XStream.toXML()
szczęśliwie zserializuje znaki sterujące obiektu Java do XML, które parser XML 1.0 odrzuci.Aby uciec przed postaciami sterującymi z Apache commons-lang, użyj
NumericEntityEscaper.below(0x20).translate(StringEscapeUtils.escapeXml(str))
źródło
public String escapeXml(String s) { return s.replaceAll("&", "&").replaceAll(">", ">").replaceAll("<", "<").replaceAll("\"", """).replaceAll("'", "'"); }
źródło
replaceAll
wywołań jest bardzo nieefektywny, szczególnie w przypadku dużych ciągów. Każde wywołanie skutkuje utworzeniem nowego obiektu String, który będzie się zawieszał do czasu zebrania śmieci. Ponadto każde wywołanie wymaga ponownego zapętlenia ciągu. Można to skonsolidować w pojedynczej ręcznej pętli z porównaniami dla każdego znaku docelowego w każdej iteracji.Podczas gdy idealizm mówi, że używaj biblioteki XML, IMHO jeśli masz podstawową koncepcję XML, wtedy zdrowy rozsądek i wydajność mówi, że szablon to wszystko. Jest też prawdopodobnie bardziej czytelny. Chociaż użycie procedur ucieczki biblioteki jest prawdopodobnie dobrym pomysłem.
Rozważ to: XML została przeznaczona do napisany przez ludzi.
Korzystaj z bibliotek do generowania XML, gdy plik XML jako „obiekt” lepiej modeluje problem. Na przykład, jeśli dołączane moduły uczestniczą w procesie tworzenia tego XML.
Edycja: jeśli chodzi o to, jak faktycznie uciec XML w szablonach, użycie CDATA lub
escapeXml(string)
z JSTL to dwa dobre rozwiązania,escapeXml(string)
można ich użyć w następujący sposób:<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <item>${fn:escapeXml(value)}</item>
źródło
Zachowanie StringEscapeUtils.escapeXml () zmieniło się z Commons Lang 2.5 na 3.0. Teraz nie wymyka się już znakom Unicode większym niż 0x7f.
To dobrze, stara metoda miała być trochę zbyt chętna do ucieczki z jednostek, które można po prostu wstawić do dokumentu utf8.
Obiecujące wydają się również nowe ucieczki, które zostaną uwzględnione w Google Guava 11.0: http://code.google.com/p/guava-libraries/issues/detail?id=799
źródło
Dla tych, którzy szukają rozwiązania najszybszego do napisania: użyj metod z apache commons-lang :
StringEscapeUtils.escapeXml10()
dla xml 1.0StringEscapeUtils.escapeXml11()
dla xml 1.1StringEscapeUtils.escapeXml()
jest obecnie przestarzały, ale w przeszłości był powszechnie używanyPamiętaj o uwzględnieniu zależności:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> <!--check current version! --> </dependency>
źródło
Uwaga: Twoje pytanie dotyczy ucieczki , a nie kodowania . Escaping polega na użyciu <itp., Aby umożliwić parserowi rozróżnienie między „to jest polecenie XML” a „to jest jakiś tekst”. Kodowanie to to, co określasz w nagłówku XML (UTF-8, ISO-8859-1 itd.).
Przede wszystkim, jak wszyscy mówili, użyj biblioteki XML. XML wygląda na prosty, ale kodowanie i ucieczka to ciemne voodoo (które zauważysz, gdy tylko napotkasz umlauty, japoński i inne dziwne rzeczy, takie jak „ cyfry o pełnej szerokości ” (& # FF11; to 1)). Zapewnienie czytelności XML dla człowieka to zadanie Syzyfa.
Sugeruję, aby nigdy nie próbować być sprytnym w kwestii kodowania tekstu i ucieczki w XML. Ale nie pozwól, aby to powstrzymało cię od prób; pamiętaj tylko, kiedy cię ugryzie (i to zrobi).
To powiedziawszy, jeśli używasz tylko UTF-8, aby uczynić rzeczy bardziej czytelnymi, możesz rozważyć tę strategię:
<![CDATA[ ... ]]>
Używam tego w edytorze SQL i umożliwia programistom wycinanie i wklejanie kodu SQL z narzędzia SQL innej firmy do XML bez martwienia się o ucieczkę. To działa, ponieważ w naszym przypadku SQL nie może zawierać umlautów, więc jestem bezpieczny.
źródło
Chociaż zasadniczo zgadzam się z Jonem Skeetem, czasami nie mam możliwości korzystania z zewnętrznej biblioteki XML. Uważam, że jest to osobliwe, że dwie funkcje pozwalające na uniknięcie / cofnięcie prostej wartości (atrybut lub znacznik, a nie pełny dokument) nie są dostępne w standardowych bibliotekach XML dołączonych do języka Java.
W rezultacie i w oparciu o różne odpowiedzi, które widziałem zamieszczone tutaj i gdzie indziej, oto rozwiązanie, które ostatecznie stworzyłem (nic nie działało jako proste kopiowanie / wklejanie):
public final static String ESCAPE_CHARS = "<>&\"\'"; public final static List<String> ESCAPE_STRINGS = Collections.unmodifiableList(Arrays.asList(new String[] { "<" , ">" , "&" , """ , "'" })); private static String UNICODE_NULL = "" + ((char)0x00); //null private static String UNICODE_LOW = "" + ((char)0x20); //space private static String UNICODE_HIGH = "" + ((char)0x7f); //should only be used for the content of an attribute or tag public static String toEscaped(String content) { String result = content; if ((content != null) && (content.length() > 0)) { boolean modified = false; StringBuilder stringBuilder = new StringBuilder(content.length()); for (int i = 0, count = content.length(); i < count; ++i) { String character = content.substring(i, i + 1); int pos = ESCAPE_CHARS.indexOf(character); if (pos > -1) { stringBuilder.append(ESCAPE_STRINGS.get(pos)); modified = true; } else { if ( (character.compareTo(UNICODE_LOW) > -1) && (character.compareTo(UNICODE_HIGH) < 1) ) { stringBuilder.append(character); } else { //Per URL reference below, Unicode null character is always restricted from XML //URL: https://en.wikipedia.org/wiki/Valid_characters_in_XML if (character.compareTo(UNICODE_NULL) != 0) { stringBuilder.append("&#" + ((int)character.charAt(0)) + ";"); } modified = true; } } } if (modified) { result = stringBuilder.toString(); } } return result; }
Powyższe obejmuje kilka różnych rzeczy:
W pewnym momencie napiszę odwrócenie tej funkcji, toUnescaped (). Po prostu nie mam dzisiaj na to czasu. Kiedy to zrobię, zaktualizuję tę odpowiedź o kod. :)
źródło
null
znak. Czy możesz wyjaśnić definicję dwóch wartościUNICODE_LOW
iUNICODE_HIGH
? Przeczytaj ponownie,if
który używa tych dwóch wartości. Uwaganull
(\u0000
która jest(int)0
) nie mieści się między tymi dwiema wartościami. Przeczytaj, w jaki sposób staje się on prawidłowo „uciekany”, tak jak WSZYSTKIE znaki Unicode istniejące poza zakresemUNICODE_LOW
iUNICODE_HIGH
, używając tej&#
techniki.Aby uniknąć znaków XML, najłatwiej jest użyć projektu Apache Commons Lang, JAR do pobrania z: http://commons.apache.org/lang/
Jest to klasa: org.apache.commons.lang3.StringEscapeUtils;
Ma metodę o nazwie „escapeXml”, która zwróci ciąg znaków o odpowiednim znaku ucieczki.
źródło
Jeśli szukasz biblioteki do wykonania pracy, spróbuj:
Guawa 26,0 udokumentowana tutaj
return XmlEscapers.xmlContentEscaper().escape(text);
Dokumentacja Apache Commons Text 1.4 tutaj
StringEscapeUtils.escapeXml11(text)
źródło
Oto proste rozwiązanie, które świetnie nadaje się również do kodowania znaków akcentowanych!
String in = "Hi Lârry & Môe!"; StringBuilder out = new StringBuilder(); for(int i = 0; i < in.length(); i++) { char c = in.charAt(i); if(c < 31 || c > 126 || "<>\"'\\&".indexOf(c) >= 0) { out.append("&#" + (int) c + ";"); } else { out.append(c); } } System.out.printf("%s%n", out);
Wyjścia
Hi Lârry & Môe!
źródło
Możesz użyć biblioteki Enterprise Security API (ESAPI) , która udostępnia metody takie jak
encodeForXML
iencodeForXMLAttribute
. Zapoznaj się z dokumentacją interfejsu Encodera ; zawiera również przykłady tworzenia instancji DefaultEncoder .źródło
Po prostu wymień
& with &
A dla innych postaci:
> with > < with < \" with " ' with '
źródło
Skorzystaj z JAXP i zapomnij o obsłudze tekstu, zostanie to zrobione automatycznie.
źródło
Spróbuj zakodować XML za pomocą serializatora Apache XML
//Serialize DOM OutputFormat format = new OutputFormat (doc); // as a String StringWriter stringOut = new StringWriter (); XMLSerializer serial = new XMLSerializer (stringOut, format); serial.serialize(doc); // Display the XML System.out.println(stringOut.toString());
źródło
Oto, co znalazłem po przeszukaniu wszędzie w poszukiwaniu rozwiązania:
Pobierz bibliotekę Jsoup:
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.12.1</version> </dependency>
Następnie:
import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Entities import org.jsoup.parser.Parser String xml = '''<?xml version = "1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope" SOAP-ENV:encodingStyle = "http://www.w3.org/2001/12/soap-encoding"> <SOAP-ENV:Body xmlns:m = "http://www.example.org/quotations"> <m:GetQuotation> <m:QuotationsName> MiscroSoft@G>>gle.com </m:QuotationsName> </m:GetQuotation> </SOAP-ENV:Body> </SOAP-ENV:Envelope>''' Document doc = Jsoup.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")), "UTF-8", "", Parser.xmlParser()) doc.outputSettings().charset("UTF-8") doc.outputSettings().escapeMode(Entities.EscapeMode.base) println doc.toString()
Mam nadzieję, że to komuś pomoże
źródło