[java] Java에서 XML 용 텍스트 데이터를 인코딩하는 가장 좋은 방법은 무엇입니까?

Java를 제외 하고이 질문 과 매우 유사합니다 .

Java에서 XML 출력에 대한 문자열 인코딩에 권장되는 방법은 무엇입니까? 문자열에는 “&”, “<“등과 같은 문자가 포함될 수 있습니다.



답변

아주 간단하게 : XML 라이브러리를 사용하십시오. 그렇게 하면 XML 사양에 대한 자세한 지식을 요구하는 대신 실제로 옳습니다 .


답변

다른 사람들이 언급했듯이 XML 라이브러리를 사용하는 것이 가장 쉬운 방법입니다. 스스로 탈출하고 싶다면 Apache Commons Lang 라이브러리 StringEscapeUtils에서 살펴볼 수 있습니다.


답변

그냥 사용하십시오.

<![CDATA[ your text here ]]>

이것은 끝을 제외한 모든 문자를 허용합니다

]]>

따라서 & 및>와 같이 불법적 인 문자를 포함 할 수 있습니다. 예를 들면.

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

그러나 CDATA 블록을 사용할 수 없으므로 속성을 이스케이프해야합니다.


답변

이것은 텍스트 문자열의 이스케이프 버전을 제공하는 데 잘 작동했습니다.

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

}


답변

이 시도:

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 년이 지났지 만 아직 완전히 정답이 아닙니다! 아니요,이 간단한 작업을 수행하기 위해 전체 타사 API를 가져올 필요는 없습니다. 나쁜 충고.

다음 방법은 다음과 같습니다.

  • 기본 다국어 평면 외부의 문자를 올바르게 처리
  • XML에 필요한 이스케이프 문자
  • 선택 사항이지만 일반적인 비 ASCII 문자를 이스케이프합니다.
  • 교체 불법 유니 코드 대체 문자와 XML 1.0의 문자. 여기에는 최선의 선택이 없습니다. 제거하는 것도 똑같이 유효합니다.

나는 가장 일반적인 경우에 최적화하려고 노력했지만 여전히 이것을 통해 / dev / random을 파이프하고 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();
}

편집 : XML을 처리 할 수있는 완벽하게 좋은 Java API가있을 때이를위한 자체 코드를 작성하는 것이 어리 석다고 계속 주장하는 사람들에게는 Oracle Java 8에 포함 된 StAX API를 알고 싶을 것입니다. ) CDATA 콘텐츠를 올바르게 인코딩하지 못합니다. 콘텐츠의]]> 시퀀스를 이스케이프하지 않습니다. Java 코어의 일부인 타사 라이브러리라도 항상 최상의 옵션은 아닙니다.


답변

StringEscapeUtils.escapeXml()제어 문자를 이스케이프하지 않습니다 (<0x20). XML 1.1은 제어 문자를 허용합니다. XML 1.0은 그렇지 않습니다. 예를 들어 XStream.toXML()는 Java 객체의 제어 문자를 XML로 직렬화하므로 XML 1.0 구문 분석기가 거부합니다.

Apache commons-lang으로 제어 문자를 이스케이프하려면 다음을 사용하십시오.

NumericEntityEscaper.below(0x20).translate(StringEscapeUtils.escapeXml(str))