Najlepszy sposób na kodowanie danych tekstowych do XML w Javie?


94

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.

Odpowiedzi:


41

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.


25
Czy może Pan polecić taką bibliotekę? (Zaskakujące jest, że nie jest to standardowa część Javy w edycji 5 ... takie częste zadanie).
Tim Cooper

4
XML jest częścią standardowego środowiska Java - zajrzyj do org.w3c.sax i org.w3c.dom. Istnieją jednak również łatwiejsze w użyciu frameworki, takie jak JDom. Zauważ, że może nie istnieć metoda „kodowania ciągów znaków dla wyjścia XML” - bardziej zalecałem, aby całe zadanie XML było wykonywane za pomocą biblioteki, a nie tylko robienie bitów naraz z manipulacją ciągami.
Jon Skeet

1
To nie jest tak przydatna rada, gdy wyprowadzam XHTML - FlyingSaucer wymaga XML, ale nie ma możliwości, bym tworzył szablon przez bibliotekę XML :). Na szczęście StringTemplate pozwala mi szybko uciec przed wszystkimi obiektami String.
Stephen,

4
@ myszy: Pytanie jest oznaczone jako Java, a Java ma wiele bibliotek XML. Rzeczywiście, istnieją interfejsy API XML wbudowane w Javę, więc nie byłoby potrzeby dodawania niczego więcej ... ale nawet gdybyś to zrobił, kilkaset KB rzadko stanowi problem poza telefonami komórkowymi w dzisiejszych czasach. Nawet gdyby nie była to Java, byłbym bardzo ostrożny podczas programowania na platformie, która nie ma żadnych interfejsów API XML ...
Jon Skeet

2
@mice: DOM API doskonale nadaje się do generowania XML. Lub są dość małe biblioteki innych firm. (Na przykład plik jar JDom ma rozmiar 114 KB). Używanie interfejsu API XML jest nadal zalecanym sposobem tworzenia XML.
Jon Skeet,

125

Jak wspominali inni, użycie biblioteki XML jest najłatwiejszym sposobem. Jeśli chcesz uciec samemu, można spojrzeć StringEscapeUtilsz Apache Commons Lang bibliotece.


To może być droga, jeśli nie zależy Ci na absolutnej poprawności, na przykład jeśli tworzysz prototyp.
Chase Seibert

2
Użyj StringEscapeUtils.escapeXml(str)z commons-lang. Używam go w aplikacji App Engine - działa jak marzenie. Oto dokument Java dla tej funkcji:
Oleg K,

Metoda escapeXml StringEscapeUtils wydaje się trochę kosztowna. Czy istnieje bardziej wydajna metoda, która działa na StringBuffer zamiast na String?
CKing

Czy ta metoda działa zarówno w przypadku zawartości, jak i atrybutów XML? Wydaje mi się, że to nie działa w przypadku atrybutów. Wydaje się, że nie ucieka \t, \ni \r.
Lii

@Lii i \t, \nczy \rtrzeba uciekać?
Betlista

20

Po prostu użyj.

<![CDATA[ your text here ]]>

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.


11
W większości przypadków nie należy tego robić. Zbyt wiele osób nadużywa znaczników CDATA. Intencją CDATA jest poinformowanie procesora, aby nie przetwarzał go jako XML i po prostu przepuścił. Jeśli próbujesz utworzyć plik XML, powinieneś tworzyć XML, a nie tylko przepuszczać bajty przez jakiś element opakowujący.
Mads Hansen

2
@Mads, użycie CDATA daje prawidłowy plik XML, więc jest to równie dobre, jak zrobienie tego we „właściwy sposób”. Jeśli ci się to nie podoba, następnie przeanalizuj je, przekształć tożsamość i wydrukuj.
Thorbjørn Ravn Andersen

24
Jeśli zawiniesz tekst w elemencie CDATA, musisz pominąć znacznik zamykający CDATA: "]]>" ... z wyjątkiem tego, że nie możesz tego uniknąć. Zamiast tego musisz podzielić swój kod na części, w których połowę danych umieszczasz w jednym elemencie CDATA, a drugą połowę w sekundę: <! [CDATA [Te dane zawierają znacznik zamykający CDATA: "]]]]> <! [CDATA [> "dlatego to musiało zostać podzielone.]]> ... Ostatecznie może być o wiele prościej zamiast tego po prostu uciec '<', '>' i '&'. Oczywiście wiele aplikacji ignoruje potencjalny problem ze znacznikami zamykającymi CDATA w danych. Myślę, że ignorancja jest błogością. :)
Stijn de Witt,

3
@StijndeWitt ma całkowitą rację. CDATA nie jest panaceum na unikanie znaków specjalnych.
dnault

To jest zły pomysł. CDATA nie zezwala na żadne znaki poza kodowaniem XML.
Florian F

14

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. "&lt;A &amp; B &gt;"
 * .... (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();
}

}

1
stringBuffer.append ("& #" + (int) ch + ";"); To nie zadziała w przypadku znaków wielobajtowych. W tej chwili wpadam w to ze znakiem emoji, sekwencją UTF8 F0 9F 98 8D.
Kylar,

14

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("&lt;"); break;
      case '>': sb.append("&gt;"); break;
      case '\"': sb.append("&quot;"); break;
      case '&': sb.append("&amp;"); break;
      case '\'': sb.append("&apos;"); break;
      default:
         if(c>0x7e) {
            sb.append("&#"+((int)c)+";");
         }else
            sb.append(c);
      }
   }
   return sb.toString();
}

8
Widzę co najmniej dwa błędy. Jedna jest subtelna, druga nie. Nie miałbym takiego błędu - ponieważ w pierwszej kolejności nie wymyślałbym na nowo koła.
Jon Skeet,

1
Iterowanie po łańcuchach Unicode jest nieco bardziej skomplikowane. Zobacz tutaj: stackoverflow.com/q/1527856/402322
ceving

1
Nie jestem pewien, czy jest subtelny, ale lepiej rozważyć przypadek, w którym t==null.
Myobis

1
@ user1003916: Zmiana znaczenia XML została zaprojektowana do konwersji dowolnego & wystąpienia na & amp; więc tak to musi działać. Jeśli excape już uciekł ciąg znaków, to twoja wina.
Pointer Null

3
Jestem zadowolony z ostatecznej wersji. Java SE jest kompaktowa, szybka i wydajna. Robienie tego, co trzeba zrobić, zamiast pobierania kolejnych 100 MB oprogramowania typu bloatware jest zawsze lepsze w mojej książce.
Roger F. Gay

11

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:

  • poprawnie obsługuje znaki poza podstawową płaszczyzną wielojęzyczności
  • znaki zmiany znaczenia wymagane w XML
  • uciec przed wszystkimi znakami spoza ASCII, co jest opcjonalne, ale powszechne
  • zamień niedozwolone znaki w XML 1.0 na znak podstawienia Unicode. Nie ma tutaj najlepszej opcji - ich usunięcie jest równie ważne.

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("&#xfffd;");   // Unicode replacement character
            } else {
                switch(c) {
                  case '&':  sb.append("&amp;"); break;
                  case '>':  sb.append("&gt;"); break;
                  case '<':  sb.append("&lt;"); break;
                  // Uncomment next two if encoding for an XML attribute
//                  case '\''  sb.append("&apos;"); break;
//                  case '\"'  sb.append("&quot;"); break;
                  // Uncomment next three if you prefer, but not required
//                  case '\n'  sb.append("&#10;"); break;
//                  case '\r'  sb.append("&#13;"); break;
//                  case '\t'  sb.append("&#9;"); 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("&#xfffd;");   // 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ą.


+1 dla samodzielnego kodu. Po prostu porównując twój kod z implementacją guawy , zastanawiam się, co z '\ t', '\ n', '\ r'? Zobacz także notatki w guava docs
jschnasse

2
Nie ma potrzeby ucieczki \ n, \ r i \ t, są one prawidłowe, chociaż sprawiają, że formatowanie jest trochę brzydkie. Zmodyfikowałem kod, aby pokazać, jak je wymknąć, jeśli tego chcesz.
Mike B

1
Nie ma sposobu na „ucieczkę]]>” w CDATA.
kmkaplan

1
Następnie powinien odrzucić zawartość, zgłaszając wyjątek IllegalArgumentException. W żadnym wypadku nie powinien twierdzić, że się powiódł, ale nadal wyświetla nieprawidłowy plik XML.
Mike B

Zamiast zastępować niedozwolone znaki w XML 1.0 znakiem podstawienia Unicode, możesz użyć moich metod tutaj stackoverflow.com/a/59475093/3882565 .
stonar96

8

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

7
public String escapeXml(String s) {
    return s.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
}

5
Łańcuch replaceAllwywoł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.
daiscog

To powinna być akceptowana odpowiedź, nawet jeśli jest nieefektywna. Rozwiązuje problem w jednej linii.
Stimpson Cat

I ma wiele błędów. Zobacz ten komentarz powyżej
David Balažic,

Aby naprawić te błędy, możesz dodatkowo użyć mojej metody tutaj stackoverflow.com/a/59475093/3882565 . Należy pamiętać, że nie jest to zamiennik, ale można go użyć dodatkowo.
stonar96

6

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>

6

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


1
Oto escaper XML Guavy: code.google.com/p/guava-libraries/source/browse/guava/src/com/… . Ogólnie stwierdziłem, że Guava jest lepiej zaprojektowana niż Apache Commons.
jhclark


6

Dla tych, którzy szukają rozwiązania najszybszego do napisania: użyj metod z apache commons-lang :

Pamię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>

5

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ę:

  • Jeśli tekst zawiera „<”, „>” lub „&”, zawiń go <![CDATA[ ... ]]>
  • Jeśli tekst nie zawiera tych trzech znaków, nie zniekształcaj go.

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.


5

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[] {
      "&lt;"
    , "&gt;"
    , "&amp;"
    , "&quot;"
    , "&apos;"
  }));

  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:

  1. unika używania logiki opartej na znakach, dopóki nie jest to absolutnie konieczne - poprawia zgodność z Unicode
  2. stara się być tak skutecznym, jak to tylko możliwe, biorąc pod uwagę prawdopodobieństwo, że drugi warunek „jeśli” jest prawdopodobnie najczęściej używaną ścieżką
  3. jest czystą funkcją; ie jest bezpieczny dla wątków
  4. ładnie optymalizuje się z wyrzucaniem elementów bezużytecznych, zwracając zawartość StringBuilder tylko wtedy, gdy coś faktycznie się zmieniło - w przeciwnym razie zwracany jest oryginalny ciąg

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. :)


Według mnie, wygląda całkiem dobrze. Nie chcę dodawać kolejnego słoika do mojego projektu tylko dla jednej metody. Jeśli udzielisz pozwolenia, czy mogę skopiować i wkleić Twój kod do mojego?
RuntimeException

1
@SatishMotwani Oczywiście możesz wziąć powyższy kod i zrobić z nim, jak chcesz. Rozumiem, że zakłada się, że każdy kod opublikowany w StackOverflow jest wolny od praw autorskich (nie jest objęty całkowitym dziełem). Z drugiej strony komuś byłoby niezmiernie trudno wnieść jakiekolwiek roszczenie dotyczące praw autorskich i oczekiwać dla siebie jakiegoś rezultatu.
chaotic3quilibrium

1
Dzięki za pozwolenie :-) Użyję go.
RuntimeException

Zapomniałeś obsługiwać znaków NUL. I może też inne rzeczy.
David Balažic

@ DavidBalažic OK, proszę wyjaśnić bardziej szczegółowo, co mogłem przegapić? Przeczytaj uważniej kod. Obsługiwałem KAŻDY POJEDYNCZY znak Unicode (z 1111 998), w tym nullznak. Czy możesz wyjaśnić definicję dwóch wartości UNICODE_LOWi UNICODE_HIGH? Przeczytaj ponownie, ifktóry używa tych dwóch wartości. Uwaga null( \u0000któ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 zakresem UNICODE_LOWi UNICODE_HIGH, używając tej &#techniki.
chaotic3quilibrium


3

Jeśli szukasz biblioteki do wykonania pracy, spróbuj:

  1. Guawa 26,0 udokumentowana tutaj

    return XmlEscapers.xmlContentEscaper().escape(text);

    Uwaga: istnieje również plik xmlAttributeEscaper()

  2. Dokumentacja Apache Commons Text 1.4 tutaj

    StringEscapeUtils.escapeXml11(text)

    Uwaga: jest też escapeXml10()metoda


1

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&#226;rry &#38; M&#244;e!

Czy „31” w pierwszym wierszu „jeśli” nie powinno wynosić „32”; tj. mniej niż znak spacji? A jeśli „31” musi pozostać, to czy nie należy go poprawić, aby przeczytać „if (c <= 31 || ...” (dodatkowy znak równości po znaku mniej niż)?
chaotic3quilibrium


1

Po prostu wymień

 & with &amp;

A dla innych postaci:

> with &gt;
< with &lt;
\" with &quot;
' with &apos;

0

Skorzystaj z JAXP i zapomnij o obsłudze tekstu, zostanie to zrobione automatycznie.


Twój link jest w języku hiszpańskim, co nie jest zbyt pomocne dla większości z nas. Lepszy jest ten .
Vivit

0

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

0

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.