Cách tốt nhất để mã hóa dữ liệu văn bản cho XML trong Java?


93

Rất giống với câu hỏi này , ngoại trừ Java.

Cách mã hóa chuỗi được đề xuất cho đầu ra XML trong Java là gì. Các chuỗi có thể chứa các ký tự như "&", "<", v.v.

Câu trả lời:


40

Rất đơn giản: sử dụng thư viện XML. Bằng cách đó, nó sẽ thực sự đúng thay vì yêu cầu kiến ​​thức chi tiết về các bit của đặc tả XML.


25
Bạn có thể giới thiệu một thư viện như vậy không? (Tôi thấy ngạc nhiên khi đây không phải là một phần tiêu chuẩn của Java phiên bản 5 ... một nhiệm vụ phổ biến như vậy).
Tim Cooper

4
XML một phần của khuôn khổ Java tiêu chuẩn - hãy tìm trong org.w3c.sax và org.w3c.dom. Tuy nhiên, cũng có một số framework dễ sử dụng hơn, chẳng hạn như JDom. Lưu ý rằng có thể không có phương thức "mã hóa chuỗi cho đầu ra XML" - tôi khuyên rằng toàn bộ tác vụ XML nên được thực hiện với một thư viện hơn là chỉ thực hiện từng bit với thao tác chuỗi.
Jon Skeet

1
Đây không phải là lời khuyên hữu ích như vậy khi xuất ra XHTML - FlyingSaucer yêu cầu XML, nhưng không phải là tôi đang tạo mẫu thông qua XML lib :). Rất may, StringTemplate cho phép tôi nhanh chóng thoát khỏi tất cả các đối tượng String.
Stephen

4
@mice: Câu hỏi là Java được gắn thẻ và Java có rất nhiều thư viện XML. Thật vậy, có các API XML được đưa vào Java, vì vậy không cần phải thêm bất cứ thứ gì khác ... nhưng ngay cả khi bạn đã làm như vậy, vài trăm K hiếm khi là vấn đề bên ngoài thiết bị di động ngày nay. Thậm chí nếu nó không phải là Java, tôi sẽ rất thận trọng khi phát triển trên một nền tảng mà không có bất kỳ API XML ...
Jon Skeet

2
@mice: API DOM hoàn toàn có khả năng tạo XML. Hoặc có các thư viện bên thứ ba khá nhỏ. (Ví dụ: tệp jar của JDom là 114K.) Sử dụng API XML vẫn là cách được khuyến nghị để tạo XML.
Jon Skeet

123

Như những người khác đã đề cập, sử dụng thư viện XML là cách dễ nhất. Nếu bạn muốn thoát khỏi chính mình, bạn có thể tìm StringEscapeUtilstừ thư viện Apache Commons Lang .


Đây có thể là cách để đi nếu bạn không quan tâm đến tính đúng đắn tuyệt đối, chẳng hạn như nếu bạn đang ghép một nguyên mẫu.
Chase Seibert

2
Sử dụng StringEscapeUtils.escapeXml(str)từ commons-lang. Tôi sử dụng nó trong ứng dụng App Engine - hoạt động như một sự quyến rũ. Đây là Tài liệu Java cho chức năng này:
Oleg K

Phương thức EscapeXml của StringEscapeUtils có vẻ hơi tốn kém. Có phương pháp nào hiệu quả hơn hoạt động trên StringBuffer thay vì String không?
CKing

Phương pháp này có hoạt động cho cả nội dung và thuộc tính XML không? Đối với tôi, có vẻ như nó không hoạt động cho các thuộc tính. Nó dường như không trốn thoát \t, \n\r.
Lii

@Lii và \t, \nhoặc \rcần được thoát?
Betlista

20

Chỉ dùng.

<![CDATA[ your text here ]]>

Điều này sẽ cho phép bất kỳ ký tự nào ngoại trừ phần kết thúc

]]>

Vì vậy, bạn có thể bao gồm các ký tự bất hợp pháp như & và>. Ví dụ.

<element><![CDATA[ characters such as & and > are allowed ]]></element>

Tuy nhiên, các thuộc tính sẽ cần phải được thoát vì không thể sử dụng các khối CDATA cho chúng.


11
Trong hầu hết các trường hợp, đó không phải là điều bạn nên làm. Quá nhiều người lạm dụng các thẻ CDATA. Mục đích của CDATA là yêu cầu bộ xử lý không xử lý nó dưới dạng XML và chỉ chuyển nó qua. Nếu bạn đang cố gắng tạo một tệp XML, thì bạn nên tạo XML, không chỉ chuyển các byte qua một số phần tử gói.
Mads Hansen

2
@Mads, việc sử dụng CDATA sẽ tạo ra một tệp XML hợp lệ, vì vậy, việc thực hiện nó "đúng cách" cũng tốt. Nếu bạn không thích nó, hãy phân tích cú pháp nó sau đó, biến đổi danh tính và in nó.
Thorbjørn Ravn Andersen

24
Nếu bạn bọc văn bản trong phần tử CDATA, bạn phải thoát khỏi điểm đánh dấu đóng CDATA: "]]>" ... ngoại trừ bạn không thể thoát khỏi điều đó. Vì vậy, thay vào đó, bạn phải chia mã của mình thành nhiều phần trong đó bạn đặt một nửa dữ liệu vào một phần tử CDATA và nửa còn lại trong một giây: <! [CDATA [Dữ liệu này chứa dấu đóng CDATA: "]]]]> <! [CDATA [> "đó là lý do tại sao nó phải được chia nhỏ.]]> ... Cuối cùng, có thể đơn giản hơn nhiều khi chỉ cần thoát '<', '>' và '&' thay thế. Tất nhiên, nhiều ứng dụng bỏ qua vấn đề tiềm ẩn với các điểm đánh dấu đóng CDATA trong dữ liệu. Tôi đoán là thiếu hiểu biết. :)
Stijn de Witt

3
@StijndeWitt là hoàn toàn chính xác. CDATA không phải là thuốc chữa bách bệnh để thoát các ký tự đặc biệt.
dnault

Đây là một ý tưởng tồi. CDATA không cho phép bất kỳ ký tự nào bên ngoài bảng mã của XML.
Florian F

14

Điều này đã hoạt động tốt để tôi cung cấp phiên bản thoát của chuỗi văn bản:

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 + ";"); Điều này sẽ không hoạt động đối với các ký tự nhiều byte. Tôi đang chạy vào điều này ngay bây giờ với một ký tự biểu tượng cảm xúc, chuỗi UTF8 F0 9F 98 8D.
Kylar

14

Thử cái này:

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
Bạn có ít nhất hai lỗi mà tôi có thể thấy. Một là tinh tế, còn lại thì không. Tôi sẽ không gặp lỗi như vậy - bởi vì tôi sẽ không phát minh lại bánh xe ngay từ đầu.
Jon Skeet

1
Và việc lặp qua các chuỗi Unicode phức tạp hơn một chút. Xem tại đây: stackoverflow.com/q/1527856/402322
ngừng hoạt động

1
Không chắc nó là tinh tế nhưng tốt hơn là nên xem xét trường hợp ở đâu t==null.
Myobis 12/1213

1
@ user1003916: Thoát XML được thiết kế để chuyển đổi bất kỳ & sự cố nào thành & amp; vì vậy đó là cách nó phải hoạt động. Nếu bạn đã thoát chuỗi excape thì đó là lỗi của bạn.
Pointer Null

3
Tôi hài lòng với phiên bản cuối cùng. Java SE nhỏ gọn, nhanh chóng và hiệu quả. Chỉ làm những gì cần làm thay vì tải xuống 100 MB bloatware khác luôn tốt hơn trong cuốn sách của tôi.
Roger F. Gay

11

Câu hỏi này đã tám năm tuổi và vẫn không phải là một câu trả lời hoàn toàn chính xác! Không, bạn không cần phải nhập toàn bộ API của bên thứ ba để thực hiện tác vụ đơn giản này. Lời khuyên tệ.

Phương pháp sau sẽ:

  • xử lý chính xác các ký tự bên ngoài mặt phẳng đa ngôn ngữ cơ bản
  • các ký tự thoát bắt buộc trong XML
  • thoát khỏi bất kỳ ký tự không phải ASCII nào, là tùy chọn nhưng phổ biến
  • thay thế các ký tự bất hợp pháp trong XML 1.0 bằng ký tự thay thế Unicode. Không có tùy chọn tốt nhất ở đây - xóa chúng cũng hợp lệ.

Tôi đã cố gắng tối ưu hóa cho trường hợp phổ biến nhất, trong khi vẫn đảm bảo bạn có thể chuyển / dev / random thông qua điều này và nhận được một chuỗi hợp lệ trong 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();
}

Chỉnh sửa: đối với những người tiếp tục nhấn mạnh rằng thật ngu ngốc khi viết mã của riêng bạn cho việc này khi có các API Java hoàn toàn tốt để xử lý XML, bạn có thể muốn biết rằng API StAX được bao gồm trong Oracle Java 8 (Tôi chưa thử nghiệm các API khác ) không thể mã hóa nội dung CDATA một cách chính xác: nó không thoát]]> trình tự trong nội dung. Thư viện của bên thứ ba, thậm chí là một phần của lõi Java, không phải lúc nào cũng là lựa chọn tốt nhất.


+1 cho mã độc lập. Chỉ so sánh mã của bạn với việc triển khai ổi , tôi đang tự hỏi điều gì về '\ t', '\ n', '\ r'? Xem thêm ghi chú vào tài liệu ổi
jschnasse

2
Không cần phải thoát \ n, \ r và \ t, chúng hợp lệ, mặc dù chúng làm cho định dạng hơi xấu. Tôi đã sửa đổi mã để hiển thị cách ghi lại chúng nếu đó là những gì bạn muốn.
Mike B

1
Không cách nào để "thoát]]>" trong CDATA.
kmkaplan

1
Sau đó, nó sẽ từ chối nội dung bằng cách ném IllegalArgumentException. Trong mọi trường hợp, nó không được tuyên bố thành công nhưng vẫn xuất ra XML không hợp lệ.
Mike B

Thay vì thay thế các ký tự bất hợp pháp trong XML 1.0 bằng ký tự thay thế Unicode, bạn có thể sử dụng các phương pháp của tôi tại đây stackoverflow.com/a/59475093/3882565 .
stonar96

8

StringEscapeUtils.escapeXml()không thoát khỏi các ký tự điều khiển (<0x20). XML 1.1 cho phép các ký tự điều khiển; XML 1.0 thì không. Ví dụ: XStream.toXML()sẽ vui vẻ tuần tự hóa các ký tự điều khiển của đối tượng Java thành XML, mà trình phân tích cú pháp XML 1.0 sẽ từ chối.

Để thoát các ký tự điều khiển bằng dấu phẩy-lang Apache, hãy sử dụng

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
Chuỗi replaceAllcuộc gọi rất kém hiệu quả, đặc biệt là đối với các chuỗi lớn. Mỗi cuộc gọi dẫn đến một đối tượng Chuỗi mới được tạo, đối tượng này sẽ lơ lửng cho đến khi rác được thu gom. Ngoài ra, mỗi cuộc gọi yêu cầu lặp lại qua chuỗi. Điều này có thể được hợp nhất thành một vòng lặp thủ công duy nhất với các so sánh với mỗi ký tự mục tiêu trong mỗi lần lặp.
daiscog

Đây phải là câu trả lời được chấp nhận, ngay cả khi nó không hiệu quả. Nó giải quyết vấn đề trong một dòng duy nhất.
Stimpson Cat

Và nó có nhiều lỗi. Xem nhận xét này trên
David Balažic

Để khắc phục những lỗi này, bạn cũng có thể sử dụng phương pháp của tôi tại đây stackoverflow.com/a/59475093/3882565 . Lưu ý rằng đây không phải là thay thế mà nó có thể được sử dụng bổ sung.
stonar96

6

Trong khi chủ nghĩa duy tâm nói rằng hãy sử dụng một thư viện XML, IMHO nếu bạn có một ý tưởng cơ bản về XML thì thông thường và hiệu suất nói rằng hãy làm theo cách của nó. Nó cũng được cho là dễ đọc hơn. Mặc dù sử dụng các quy trình thoát của thư viện có lẽ là một ý kiến ​​hay.

Xem xét việc này: XML được có nghĩa là để được viết bởi con người.

Sử dụng các thư viện để tạo XML khi có XML của bạn làm "đối tượng" mô hình hóa vấn đề của bạn tốt hơn. Ví dụ: nếu các mô-đun có thể cắm được tham gia vào quá trình xây dựng XML này.

Chỉnh sửa: đối với cách thực sự thoát khỏi XML trong các mẫu, sử dụng CDATA hoặc escapeXml(string)từ JSTL là hai giải pháp tốt, escapeXml(string)có thể được sử dụng như sau:

<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<item>${fn:escapeXml(value)}</item>

6

Hành vi của StringEscapeUtils.escapeXml () đã thay đổi từ Commons Lang 2.5 thành 3.0. Bây giờ nó không còn thoát các ký tự Unicode lớn hơn 0x7f.

Đây là một điều tốt, phương pháp cũ là một chút mong muốn thoát khỏi các thực thể chỉ có thể được chèn vào tài liệu utf8.

Các trình thoát mới sẽ được đưa vào Google Guava 11.0 cũng có vẻ đầy hứa hẹn: http://code.google.com/p/guava-libraries/issues/detail?id=799


1
Đây là trình thoát XML của Guava: code.google.com/p/guava-libraries/source/browse/guava/src/com/… . Nói chung, tôi thấy Guava được cấu trúc tốt hơn Apache Commons.
jhclark


6

Đối với những người đang tìm kiếm giải pháp viết nhanh nhất: hãy sử dụng các phương thức từ apache commons-lang :

Hãy nhớ bao gồm sự phụ thuộc:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.5</version> <!--check current version! -->
</dependency>

5

Lưu ý: Câu hỏi của bạn là về thoát , không phải mã hóa . Thoát đang sử dụng <, v.v. để cho phép trình phân tích cú pháp phân biệt giữa "đây là lệnh XML" và "đây là một số văn bản". Mã hóa là nội dung bạn chỉ định trong tiêu đề XML (UTF-8, ISO-8859-1, v.v.).

Trước hết, như mọi người đã nói, hãy sử dụng thư viện XML. XML trông có vẻ đơn giản nhưng mã hóa + nội dung thoát là một điều xấu xa (bạn sẽ nhận thấy ngay khi gặp âm sắc và tiếng Nhật và những thứ kỳ lạ khác như " chữ số chiều rộng đầy đủ " (& # FF11; là 1)). Giữ cho con người có thể đọc được XML là một nhiệm vụ của Sisyphus.

Tôi khuyên bạn đừng bao giờ cố tỏ ra thông minh về mã hóa văn bản và thoát trong XML. Nhưng đừng để điều đó ngăn cản bạn cố gắng; chỉ cần nhớ khi nó cắn bạn (và nó sẽ).

Điều đó nói rằng, nếu bạn chỉ sử dụng UTF-8, để làm cho mọi thứ dễ đọc hơn, bạn có thể xem xét chiến lược này:

  • Nếu văn bản có chứa '<', '>' hoặc '&', hãy bọc nó vào <![CDATA[ ... ]]>
  • Nếu văn bản không chứa ba ký tự này, đừng làm cong nó.

Tôi đang sử dụng điều này trong trình soạn thảo SQL và nó cho phép các nhà phát triển cắt và dán SQL từ công cụ SQL của bên thứ ba vào XML mà không lo bị thoát. Điều này hoạt động vì SQL không thể chứa âm sắc trong trường hợp của chúng tôi, vì vậy tôi an toàn.


5

Mặc dù tôi đồng ý với Jon Skeet về nguyên tắc, nhưng đôi khi tôi không có tùy chọn sử dụng thư viện XML bên ngoài. Và tôi thấy điều đặc biệt là hai hàm để thoát / unescape một giá trị đơn giản (thuộc tính hoặc thẻ, không phải tài liệu đầy đủ) không có sẵn trong các thư viện XML tiêu chuẩn đi kèm với Java.

Do đó và dựa trên các câu trả lời khác nhau mà tôi đã thấy được đăng ở đây và ở những nơi khác, đây là giải pháp tôi đã tạo ra (không có gì hoạt động như một bản sao / dán đơn giản):

  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_LOW =  "" + ((char)0x20); //space
  private static String UNICODE_HIGH = "" + ((char)0x7f);

  //should only use 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 {
            stringBuilder.append("&#" + ((int)character.charAt(0)) + ";");
            modified = true;
          }
        }
      }
      if (modified) {
        result = stringBuilder.toString();
      }
    }

    return result;
  }

Những điều trên chứa đựng một số điều khác nhau:

  1. tránh sử dụng logic dựa trên ký tự cho đến khi nó hoàn toàn phải - cải thiện khả năng tương thích với unicode
  2. cố gắng trở nên hiệu quả nhất có thể với xác suất là điều kiện "nếu" thứ hai có khả năng là con đường được sử dụng nhiều nhất
  3. là một chức năng thuần túy; tức là an toàn theo chủ đề
  4. tối ưu hóa độc đáo với trình thu gom rác bằng cách chỉ trả lại nội dung của StringBuilder nếu có điều gì đó thực sự thay đổi - nếu không, chuỗi gốc sẽ được trả về

Tại một số điểm, tôi sẽ viết ngược lại của hàm này, toUnescaped (). Tôi chỉ không có thời gian để làm điều đó ngày hôm nay. Khi tôi làm vậy, tôi sẽ cập nhật câu trả lời này với mã. :)


Nhìn có vẻ khá tốt đối với tôi. Tôi không muốn thêm một jar khác vào dự án của mình chỉ cho một phương thức. Nếu bạn vui lòng cấp quyền, tôi có thể sao chép và dán mã của bạn vào mã của tôi không?
RuntimeException

1
@SatishMotwani Tất nhiên bạn có thể lấy đoạn mã trên và làm với nó tùy thích. Tôi hiểu rằng bất kỳ mã nào được xuất bản trên StackOverflow đều được coi là miễn phí bản quyền (không được coi là một tác phẩm toàn bộ). Mặt khác, sẽ cực kỳ khó khăn cho một người nào đó nhấn mạnh bất kỳ loại khiếu nại bản quyền nào và mong đợi một kết quả cho chính họ.
hỗn loạn3 trạng thái cân bằng

1
Cảm ơn vì đã cho phép :-) Tôi sẽ sử dụng nó.
RuntimeException

Bạn quên xử lý các ký tự NUL. Và có thể những thứ khác nữa.
David Balažic

3

Để thoát các ký tự XML, cách dễ nhất là sử dụng dự án Apache Commons Lang, có thể tải xuống JAR từ: http://commons.apache.org/lang/

Lớp này là: org.apache.commons.lang3.StringEscapeUtils;

Nó có một phương thức có tên là "EscapeXml", sẽ trả về một Chuỗi đã thoát thích hợp.


Cập nhật: EscapeXml hiện không được dùng nữa - hãy sử dụng EscapeXml10. Tham khảo commons.apache.org/proper/commons-lang/javadocs/api-3.3/org/…
Daniel

3

Nếu bạn đang tìm kiếm một thư viện để hoàn thành công việc, hãy thử:

  1. Ổi 26.0 ghi lại ở đây

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

    Lưu ý: Ngoài ra còn có một xmlAttributeEscaper()

  2. Apache Commons Text 1.4 tài liệu tại đây

    StringEscapeUtils.escapeXml11(text)

    Lưu ý: Ngoài ra còn có một escapeXml10()phương pháp


1

Đây là một giải pháp dễ dàng và nó cũng tuyệt vời để mã hóa các ký tự có dấu!

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

Kết quả đầu ra

Hi L&#226;rry &#38; M&#244;e!

Không nên "31" ở dòng đầu tiên của "nếu" là "32"; tức là ít hơn ký tự khoảng trắng? Và nếu "31" phải tồn tại, sau đó không nên nó được sửa chữa để đọc "if (c <= 31 || ..." (bình đẳng thêm ký sau dấu nhỏ hơn)?
chaotic3quilibrium


1

Chỉ cần thay thế

 & with &amp;

Và đối với các nhân vật khác:

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

0

Sử dụng JAXP và quên việc xử lý văn bản, nó sẽ được thực hiện tự động cho bạn.


Liên kết của bạn bằng tiếng Tây Ban Nha, điều này không quá hữu ích đối với hầu hết chúng ta. Tốt hơn là cái này .
Vivit

0

Cố gắng mã hóa XML bằng cách sử dụng bộ tuần tự 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

Đây là những gì tôi tìm thấy sau khi tìm kiếm khắp nơi để tìm giải pháp:

Tải thư viện Jsoup:

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.12.1</version>
</dependency>

Sau đó:

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

Hy vọng điều này sẽ giúp ai đó

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.