Я передаю xml в clob из источника oracle в java, который затем подписывает xml и возвращает результат, однако возвращенный результат содержит специальные символы. F.E.Специальные символы в xml при преобразовании из документа в clob
ввод XML:
<a>žė</a>
выход XML:
<a>žė</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");
не делает трюк.
Какова кодировка XML, созданная 'getClobVal()'? – kgeorgiy
Вы имеете в виду это? xml version = "1.0" encoding = "UTF-8"?> –
Да. Я ожидал увидеть что-то вроде «US-ASCII», что абсолютно совместимо со всем, но требует много побегов. – kgeorgiy