[java] GAE에서 완벽하게 유효한 XML을 구문 분석 할 때 “내용이 프롤로그에 허용되지 않습니다”

나는 지난 48 시간 동안이 절대적으로 분노한 벌레에 대해 머리를 치고 있었기 때문에 마침내 타월을 던져 여기에서 물어 보겠다고 생각했다.

AWS SimpleDB에 대한 호출에서 응답 XML을 구문 분석하려고합니다. 응답은 정상적으로 돌아오고 있습니다. 예를 들어 다음과 같을 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
    <ListDomainsResult>
        <DomainName>Audio</DomainName>
        <DomainName>Course</DomainName>
        <DomainName>DocumentContents</DomainName>
        <DomainName>LectureSet</DomainName>
        <DomainName>MetaData</DomainName>
        <DomainName>Professors</DomainName>
        <DomainName>Tag</DomainName>
    </ListDomainsResult>
    <ResponseMetadata>
        <RequestId>42330b4a-e134-6aec-e62a-5869ac2b4575</RequestId>
        <BoxUsage>0.0000071759</BoxUsage>
    </ResponseMetadata>
</ListDomainsResponse>

이 XML을 파서에 전달합니다.

XMLEventReader eventReader = xmlInputFactory.createXMLEventReader(response.getContent());

eventReader.nextEvent();원하는 데이터를 얻기 위해 여러 번 전화를 겁니다 .

여기에 기괴한 부분이 있습니다. 로컬 서버에서 잘 작동합니다. 응답이 들어오고 파싱하면 모두가 행복합니다. 문제는 Google App Engine에 코드를 배포 할 때 나가는 요청이 계속 작동하고 응답 XML이 100 % 동일하고 정확 해 보이지만 응답이 다음 예외와 함께 구문 분석에 실패한다는 것입니다.

com.amazonaws.http.HttpClient handleResponse: Unable to unmarshall response (ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.): <?xml version="1.0" encoding="utf-8"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/"><ListDomainsResult><DomainName>Audio</DomainName><DomainName>Course</DomainName><DomainName>DocumentContents</DomainName><DomainName>LectureSet</DomainName><DomainName>MetaData</DomainName><DomainName>Professors</DomainName><DomainName>Tag</DomainName></ListDomainsResult><ResponseMetadata><RequestId>42330b4a-e134-6aec-e62a-5869ac2b4575</RequestId><BoxUsage>0.0000071759</BoxUsage></ResponseMetadata></ListDomainsResponse>
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.
    at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(Unknown Source)
    at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(Unknown Source)
    at com.amazonaws.transform.StaxUnmarshallerContext.nextEvent(StaxUnmarshallerContext.java:153)
    ... (rest of lines omitted)

이 XML을 ‘보이지 않는 문자’또는 UTF8이 아닌 인코딩 된 문자 등에 대해 이중, 삼중, 사중으로 확인했습니다. 바이트 순서 표시 또는 그 성격의 배열에서 바이트 단위로 살펴 보았습니다. 아무것도; 내가 던질 수있는 모든 검증 테스트를 통과합니다. 더 이상하게도 Saxon 기반 파서를 사용하면 발생하지만 GAE에서만 항상 로컬 환경에서 잘 작동합니다.

완벽하게 작동하는 환경에서만 디버거를 실행할 수있을 때 문제에 대한 코드를 추적하기가 매우 어렵습니다 (GAE에서 원격으로 디버깅하는 좋은 방법을 찾지 못했습니다). 그럼에도 불구하고 기본 수단을 사용하여 다음을 포함하여 백만 가지 접근 방식을 시도했습니다.

  • 프롤로그가 있거나없는 XML
  • 줄 바꿈 포함 및 제외
  • 프롤로그에 “encoding =”속성이 있거나없는 경우
  • 두 개행 스타일
  • HTTP 스트림에 청킹 정보가있는 경우와없는 경우

그리고 나는 그것들이 상호 작용하는 것이 합리적 인 여러 조합으로 이들 대부분을 시도했습니다. 나는 내 지혜의 끝에있다. 누구든지 이전에 이와 같은 문제를 본 적이 있습니까?

감사!



답변

XML과 XSD (또는 DTD)의 인코딩이 다릅니다.
XML 파일 헤더 : <?xml version='1.0' encoding='utf-8'?>
XSD 파일 헤더 :<?xml version='1.0' encoding='utf-16'?>

이를 유발하는 또 다른 가능한 시나리오는 XML 문서 유형 선언 이전에 무언가가 오는 경우입니다. 즉, 버퍼에 다음과 같은 내용이있을 수 있습니다.

helloworld<?xml version="1.0" encoding="utf-8"?>  

또는 공백이나 특수 문자까지.

버퍼에있을 수있는 바이트 순서 마커라는 특수 문자가 있습니다. 파서에 버퍼를 전달하기 전에 다음을 수행하십시오.

String xml = "<?xml ...";
xml = xml.trim().replaceFirst("^([\\W]+)<","<");


답변

이 오류 메시지는 항상 시작 요소의 잘못된 XML 콘텐츠로 인해 발생합니다. 예 : 아주 작은 점 “.” XML 요소의 시작 부분에 있습니다.

<?xml….” 앞의 모든 문자 는 ” org.xml.sax.SAXParseException : 프롤로그에 내용이 허용되지 않음 “오류 메시지를 유발 합니다.

작은 점“ . ”앞에“<?xml….

이 문제를 해결하려면 “<?xml“.

참고 : http://www.mkyong.com/java/sax-error-content-is-not-allowed-in-prolog/


답변

나는 같은 문제에 직면했다. 제 경우에는 XML 파일이 c # 프로그램에서 생성되고 추가 처리를 위해 AS400에 공급되었습니다. 일부 분석 후 XML 파일을 생성하는 동안 UTF8 인코딩을 사용하고있는 반면 javac (in AS400)는 “UTF8 without BOM”을 사용한다는 것을 확인했습니다. 따라서 아래에 언급 된 것과 유사한 추가 코드를 작성해야했습니다.

//create encoding with no BOM
Encoding outputEnc = new UTF8Encoding(false);
//open file with encoding
TextWriter file = new StreamWriter(filePath, false, outputEnc);

file.Write(doc.InnerXml);
file.Flush();
file.Close(); // save and close it


답변

메모장 ++에서 xml 파일을 검사하고 파일을 저장하는 동안 문제가 있었지만 상단 utf-8 xml 태그가 <?xml version="1.0" encoding="utf-8"?>

Encoding (Tab)> Encode in UTF-8 : selected (이전 Encode in UTF-8-BOM)를 사용하여 notpad ++에 파일을 저장하여 수정했습니다.


답변

xml 선언을 제거하면 해결되었습니다.

<?xml version='1.0' encoding='utf-8'?>


답변

내 xml 파일에서 헤더는 다음과 같습니다.

<?xml version="1.0" encoding="utf-16"? />

테스트 파일에서 파일 바이트를 읽고 데이터를 UTF-8로 디코딩 (이 파일의 헤더가 utf-16이라는 사실을 인식하지 못함)하여 문자열을 생성했습니다.

byte[] data = Files.readAllBytes(Paths.get(path));
String dataString = new String(data, "UTF-8");

이 문자열을 객체로 역 직렬화하려고 할 때 동일한 오류가 표시되었습니다.

javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.

두 번째 줄을

String dataString = new String(data, "UTF-16");

나는 개체를 정상적으로 역 직렬화 할 수 있었다. 따라서 Romain이 위에서 언급했듯이 인코딩이 일치해야합니다.


답변

내 xml 파일에서 “내용이 프롤로그에서 허용되지 않습니다”라는 동일한 문제에 직면했습니다.

해결책

처음에 내 루트 폴더는 ‘# Filename ‘이었습니다.

첫 번째 문자 ‘#’을 제거하면 오류가 해결되었습니다.

#filename을 제거 할 필요가 없습니다 …이 방법으로 시도하십시오 ..

Unmarshaller 메서드에 File 또는 URL 개체를 전달하는 대신 FileInputStream을 사용하십시오.

File myFile = new File("........");
Object obj = unmarshaller.unmarshal(new FileInputStream(myFile));