2016-11-08 3 views
0

xml을 oracle에서 java 소스로 전달한 다음 xml에 서명하여 결과를 반환하지만 반환 된 결과에는 특수 문자가 포함됩니다. f.e.문서에서 클로브로 변환 할 때 xml의 특수 문자

입력 XML :

<a>žė</a> 

출력 XML :

<a>&#382;&#279;</a> 

내가 특수 문자가 없습니다 자바 결과를 인쇄하려고하면

는 그러나 오라클에 내가이 얻을. 첫 번째 clob에서 문자 스트림을 가져오고 result clob에 할당하면 특수 문자가 없으며 문서를 clob로 변형 할 때만 나타납니다.

코드 재현 :

create or replace and compile java source named test_encoding as 
import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.Reader; 
import java.io.BufferedReader; 
import java.io.Writer; 
import java.io.StringWriter; 
import java.security.*; 
import java.security.cert.X509Certificate; 
import java.sql.Clob; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Collections; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.TimeZone; 

import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.transform.OutputKeys; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.Result; 
import javax.xml.transform.Source; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 

import org.w3c.dom.Attr; 
import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.NamedNodeMap; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 

import sun.misc.BASE64Encoder; 
import sun.misc.BASE64Decoder; 

public class test_encoding { 

    public static Clob getxml(Clob inputClob, Clob outputClob) throws Exception{ 

    Document document = getDocument(inputClob); 

    //outputClob = inputClob; 
    //String inputString = getStringFromIS(readerToInputStream(inputClob.getCharacterStream())); 
    String inputString = getStringFromIS(getInputStreamFromDocument(document)); 
    Writer writer = outputClob.setCharacterStream(1); 
    writer.write(inputString.toCharArray()); 
    writer.close(); 

    return outputClob; 

    } 

    public static InputStream readerToInputStream(Reader reader) throws Exception { 
    char[] charBuffer = new char[8 * 1024]; 
    StringBuilder builder = new StringBuilder(); 
    int numCharsRead; 
    while ((numCharsRead = reader.read(charBuffer, 0, charBuffer.length)) != -1) { 
     builder.append(charBuffer, 0, numCharsRead); 
    } 

    return new ByteArrayInputStream(builder.toString().getBytes("UTF-8")); 
    } 

    public static String getStringFromIS(InputStream is) throws Exception { 
     BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); 
     String str = ""; 
     String line; 
     while ((line = in.readLine()) != null) { 
      str = str.concat(line); 
     } 

     return str; 
    } 

    public static Document getDocument(Clob xmlClob) throws Exception { 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    dbf.setNamespaceAware(true); 

    return dbf.newDocumentBuilder().parse(readerToInputStream(xmlClob.getCharacterStream())); 
    } 

    public static InputStream getInputStreamFromElement(Element element) throws Exception { 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     Source xmlSource = new DOMSource(element); 
     Result outputTarget = new StreamResult(outputStream); 
     TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); 
     InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); 

     return is; 
    } 

    public static InputStream getInputStreamFromDocument(Document document) throws Exception { 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     Source xmlSource = new DOMSource(document); 
     Result outputTarget = new StreamResult(outputStream); 
     TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); 
     InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); 

     return is; 
    } 

} 

PLSQL 기능 :

create or replace function test_encoding(
    p_input_clob clob, 
    p_output_clop clob) 
--return varchar2 as 
return clob as 
    --language java name 'SignXMLNew.signXml(java.sql.Clob, java.lang.String, java.lang.String, java.lang.String, java.lang.String) return java.lang.String'; 
    language java name 'test_encoding.getxml(java.sql.Clob, java.sql.Clob) return java.sql.Clob'; 

스크립트

declare 
    l_input_xml clob := xmlType('<a>žė</a>').getClobVal(); 
    l_output_xml clob; 
begin 
    dbms_lob.createtemporary(l_output_xml, false); 
    dbms_output.put_line(l_input_xml); 
    l_output_xml := test_encoding(l_input_xml, l_output_xml); 
    dbms_output.put_line(l_output_xml); 
end; 
/

UPDATE

핀 포인트를 문자 "žė"가 html 문자로 변환되는 위치. 그것은 문서를 변형하는 것입니다. 나는 문서를 byte []로 변형 시켰고 그것을 인쇄 한 hexadical 표현과 html 특수 문자가 이미있다. 나는 이클립스에서 동일한 작업을 수행 했으므로 html 문자가 없다. f.e.

Result in oracle: 3C613E26233338323B26233237393B3C2F613E 
Result in eclipse: 3C613EC5BEC4973C2F613E 

나는 오라클과 이클립스 모두에서 [] 바이트와 바이트 배열의있는 16 진수 표현을 출력 할 문서를 변환 정확히 동일한 기능을 사용하고 있습니다. 문서를 변환하는

기능은 [] 바이트 :

public static byte[] getDocumentByteArray(Document doc) throws Exception { 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    Source xmlSource = new DOMSource(doc); 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 
    Result outputTarget = new StreamResult(outputStream); 
    transformer.transform(xmlSource, outputTarget); 

    return outputStream.toByteArray(); 
} 

public static String bytesToHex(byte[] bytes) { 
    char[] hexArray = "ABCDEF".toCharArray(); 
    char[] hexChars = new char[bytes.length * 2]; 
    for (int j = 0; j < bytes.length; j++) { 
     int v = bytes[j] & 0xFF; 
     hexChars[j * 2] = hexArray[v >>> 4]; 
     hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
    } 
    return new String(hexChars); 
} 

는 그 변압기 내 PC의 NLS_LANG에서 인코딩을 받아 오라클은 오라클 서버의 NLS_LANG 소요 이클립스, 예를 들어, 로케일 인코딩 소요 될 수 있습니다. 그렇다면 어떤 인코딩을 사용할지 지정하려면 어떻게해야합니까?

transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 

트릭을 수행하지 마십시오.

+1

getClobVal()에 의해 생성 된 XML의 인코딩은 무엇입니까? – kgeorgiy

+0

이 뜻이십니까?

+1

예. 저는 "US-ASCII"와 같은 것을 보았습니다. 모든것과 완벽하게 호환되지만, 많은 탈출이 필요합니다. – kgeorgiy

답변

0

oracle에서 사용할 때 Transformer의 버그가있는 것 같습니다. DOMParser, XMLDocument and XMLElement을 사용하여이 문제를 해결할 수있는 방법을 찾았습니다. 이들을 사용하여 모든 코드를 다시 작성하는 작업이 너무 많으면 값을 반환하기 전에 끝에 XML을 사용하여 간단히 XML을 변형 할 수 있습니다. f.e.

... 
InputStream elementIS = getInputStreamFromElement(soapEnvelope); 
retClob = setCharacterStream(elementIS, retClob); 

return retClob; 

public static InputStream getInputStreamFromElement(Element element) throws Exception { 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    Source xmlSource = new DOMSource(element); 
    Result outputTarget = new StreamResult(outputStream); 
    TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); 
    InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); 

    return is; 
} 

public static Clob setCharacterStream(InputStream inputStream, Clob clob) throws Exception{ 
    DOMParser parser = new DOMParser(); 
    parser.parse(inputStream); 
    XMLDocument xmlDocument = parser.getDocument(); 
    XMLElement xmlPayload = (XMLElement) xmlDocument.getDocumentElement(); 
    Writer writer = clob.setCharacterStream(1); 
    xmlPayload.print(writer); 

    return clob; 
}