2016-11-08 9 views
0

Я передаю xml в clob из источника oracle в java, который затем подписывает xml и возвращает результат, однако возвращенный результат содержит специальные символы. F.E.Специальные символы в xml при преобразовании из документа в clob

ввод XML:

<a>žė</a> 

выход XML:

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

Если я пытаюсь распечатать результат в Java нет никаких специальных символов, однако в оракула я получить эти. Если я получаю поток символов из первого clob и присваиваю результат 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

Pinpoint ed, где символ «žė» преобразуется в html-символы. Это при преобразовании документа. Я преобразовал документ в байт [], и там было напечатано его шестигранное представление и специальные символы html. Я сделал то же самое в Eclipse, и там нет html-символов. F.E.

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

Я использую одни и ту же функцию для преобразования документа в байтах [] и распечатать hexademical представления массива байт, как в Oracle и в Eclipse.

Функция для преобразования документа в байт []:

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

Может быть, что трансформатор имеет кодировку локали, например, в затмении он принимает кодировку из NLS_LANG моего компьютера и в оракула он принимает оракулов серверов NLS_LANG. Если да, то как я могу указать, какую кодировку использовать, потому что кажется, что

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

не делает трюк.

+1

Какова кодировка XML, созданная 'getClobVal()'? – kgeorgiy

+0

Вы имеете в виду это?

+1

Да. Я ожидал увидеть что-то вроде «US-ASCII», что абсолютно совместимо со всем, но требует много побегов. – kgeorgiy

ответ

0

Похоже, что есть ошибка с Transformer при использовании в оракуле. Мы решили обходное решение для этого, используя DOMParser, XMLDocument and XMLElement. Если есть слишком много работы, чтобы переписать весь код, используя их, вы можете просто преобразовать 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; 
}