Могу ли я заставить JAXB не преобразовывать "в", например, при сортировке XML?
У меня есть объект, который сортируется по XML с помощью JAXB. Один элемент содержит строку, которая включает в себя кавычки ( "). В результате XML имеет "
, где" существует ".
Несмотря на то, что это обычно предпочтительнее, мне нужно, чтобы мой результат соответствовал устаревшей системе. Как заставить JAXB НЕ преобразовывать объекты HTML?
-
Спасибо за ответы. Тем не менее, я никогда не вижу вызов обработчика(). Можете ли вы взглянуть и посмотреть, что я делаю неправильно? Спасибо!
package org.dc.model;
import java.io.IOException;
import java.io.Writer;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.dc.generated.Shiporder;
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
public class PleaseWork {
public void prettyPlease() throws JAXBException {
Shiporder shipOrder = new Shiporder();
shipOrder.setOrderid("Order ID");
shipOrder.setOrderperson("The woman said, \"How ya doin & stuff?\"");
JAXBContext context = JAXBContext.newInstance("org.dc.generated");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(CharacterEscapeHandler.class.getName(),
new CharacterEscapeHandler() {
@Override
public void escape(char[] ch, int start, int length,
boolean isAttVal, Writer out) throws IOException {
out.write("Called escape for characters = " + ch.toString());
}
});
marshaller.marshal(shipOrder, System.out);
}
public static void main(String[] args) throws Exception {
new PleaseWork().prettyPlease();
}
}
-
Вывод:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<shiporder orderid="Order ID">
<orderperson>The woman said, "How ya doin & stuff?"</orderperson>
</shiporder>
и, как вы можете видеть, обратный вызов никогда не отображается. (Как только я получаю вызов callback, я буду беспокоиться о том, что он действительно делает то, что я хочу.)
-
Ответы
Ответ 1
Решение моего товарища по команде найдено:
PrintWriter printWriter = new PrintWriter(new FileWriter(xmlFile));
DataWriter dataWriter = new DataWriter(printWriter, "UTF-8", DumbEscapeHandler.theInstance);
marshaller.marshal(request, dataWriter);
Вместо передачи xmlFile в marshal() передайте DataWriter, который знает как кодировку, так и соответствующий обработчик эвакуации, если таковой имеется.
Примечание. Поскольку DataWriter и DumbEscapeHandler находятся в пакете com.sun.xml.internal.bind.marshaller, вы должны загружать javac.
Ответ 2
Я только что сделал свой собственный обработчик как класс, подобный этому:
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
public class XmlCharacterHandler implements CharacterEscapeHandler {
public void escape(char[] buf, int start, int len, boolean isAttValue,
Writer out) throws IOException {
StringWriter buffer = new StringWriter();
for (int i = start; i < start + len; i++) {
buffer.write(buf[i]);
}
String st = buffer.toString();
if (!st.contains("CDATA")) {
st = buffer.toString().replace("&", "&").replace("<", "<")
.replace(">", ">").replace("'", "'")
.replace("\"", """);
}
out.write(st);
System.out.println(st);
}
}
в методе маршаллера просто вызывается:
marshaller.setProperty(CharacterEscapeHandler.class.getName(),
new XmlCharacterHandler());
он отлично работает.
Ответ 3
Я немного играл с вашим примером и отлаживал код JAXB. И, похоже, что-то специфическое в кодировке UTF-8. Свойство escapeHandler MarshallerImpl
кажется правильным. Однако он используется не в каждом контексте. Если я искал вызовы MarshallerImpl.createEscapeHandler()
, я обнаружил:
public XmlOutput createWriter( OutputStream os, String encoding ) throws JAXBException {
// UTF8XmlOutput does buffering on its own, and
// otherwise createWriter(Writer) inserts a buffering,
// so no point in doing a buffering here.
if(encoding.equals("UTF-8")) {
Encoded[] table = context.getUTF8NameTable();
final UTF8XmlOutput out;
if(isFormattedOutput())
out = new IndentingUTF8XmlOutput(os,indent,table);
else {
if(c14nSupport)
out = new C14nXmlOutput(os,table,context.c14nSupport);
else
out = new UTF8XmlOutput(os,table);
}
if(header!=null)
out.setHeader(header);
return out;
}
try {
return createWriter(
new OutputStreamWriter(os,getJavaEncoding(encoding)),
encoding );
} catch( UnsupportedEncodingException e ) {
throw new MarshalException(
Messages.UNSUPPORTED_ENCODING.format(encoding),
e );
}
}
Обратите внимание, что в вашей настройке учитывается верхняя секция (...equals("UTF-8")...)
. Однако это не принимает escapeHandler
. Однако, если вы установите кодировку на любой другой, нижняя часть этого метода вызывается (createWriter(OutputStream, String)
), и в этом случае используется escapeHandler
, поэтому EH играет свою роль.
Итак, добавив...
marshaller.setProperty(Marshaller.JAXB_ENCODING, "ASCII");
вызывается ваш пользовательский CharacterEscapeHandler
.
Не совсем уверен, но я бы предположил, что это ошибка в JAXB.
Ответ 4
@ Elliot вы можете использовать это, чтобы включить маршаллера в функцию characterEscape.
Это странно, но оно работает, если вы установите " Unicode" вместо "UTF-8".
Добавьте это до или после установки свойства CharacterEscapeHandler.
marshaller.setProperty(Marshaller.JAXB_ENCODING, "Unicode");
Однако не уверен только, только проверив консоль внутри вашей IDE, потому что она должна отображаться в зависимости от кодировки рабочей области. Лучше также проверить это из файла:
marshaller.marshal(shipOrder, new File("C:\\shipOrder.txt"));
Ответ 5
Похоже, это возможно с реализация Sun JAXB, хотя я сам этого не делал.
Ответ 6
Я проверил спецификацию XML. http://www.w3.org/TR/REC-xml/#sec-references говорит, что "хорошо сформированные документы не должны объявлять ни одно из следующих объектов: amp, lt, gt, apos, quot." so похоже, что парсер XML, используемый устаревшей системой, не соответствует.
(Я знаю, что он не решает вашу проблему, но, по крайней мере, приятно сказать, какой компонент нарушен).
Ответ 7
Это работает для меня после прочтения других сообщений:
javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(object);
marshaller = jc.createMarshaller(); marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());
public static class CustomCharacterEscapeHandler implements CharacterEscapeHandler {
/**
* Escape characters inside the buffer and send the output to the Writer.
* (prevent <b> to be converted <b> but still ok for a<5.)
*/
public void escape(char[] buf, int start, int len, boolean isAttValue, Writer out) throws IOException {
if (buf != null){
StringBuilder sb = new StringBuilder();
for (int i = start; i < start + len; i++) {
char ch = buf[i];
//by adding these, it prevent the problem happened when unmarshalling
if (ch == '&') {
sb.append("&");
continue;
}
if (ch == '"' && isAttValue) {
sb.append(""");
continue;
}
if (ch == '\'' && isAttValue) {
sb.append("'");
continue;
}
// otherwise print normally
sb.append(ch);
}
//Make corrections of unintended changes
String st = sb.toString();
st = st.replace("&quot;", """)
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&apos;", "'")
.replace("&amp;", "&");
out.write(st);
}
}
}
Ответ 8
Я бы сказал, что самый простой способ - переопределить CharacterEscapeHandler
:
marshaller.setProperty("com.sun.xml.bind.characterEscapeHandler", new CharacterEscapeHandler() {
@Override
public void escape(char[] ch, int start, int length, boolean isAttVal,
Writer out) throws IOException {
out.write(ch, start, length);
}
});
Ответ 9
я нашел ту же проблему
Я исправил это с помощью xmlWriter
в файле xmlWriter есть один метод isEscapeText() и setEscapeTest
это по умолчанию true
если вы не хотите, чтобы преобразование между < to & lt это время вам нужно установитьEscapeTest (false); во время сортировки
JAXBContext jaxbContext = JAXBContext.newInstance(ваш класс); Маршаллер-маршаллер = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Create a filter that will remove the xmlns attribute
NamespaceFilter outFilter = new NamespaceFilter(null, false);
// Do some formatting, this is obviously optional and may effect
// performance
OutputFormat format = new OutputFormat();
format.setIndent(true);
format.setNewlines(true);
// Create a new org.dom4j.io.XMLWriter that will serve as the
// ContentHandler for our filter.
XMLWriter writer = new XMLWriter(new FileOutputStream(file), format);
***writer.setEscapeText(false);***
// Attach the writer to the filter
outFilter.setContentHandler(writer);
// marshalling
marshaller.marshal(piaDto, outFilter);
marshaller.marshal(piaDto, System.out);
это изменение writer.setEscapeText(false); исправлено мое сообщение
надеюсь, что это изменит вам полезность
Ответ 10
интересно, но со строками вы можете попробовать
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(data, sw);
sw.toString();
по крайней мере для меня это не избежать кавычек
Ответ 11
Самый простой способ использования Sun Marshaller - предоставить вам собственную реализацию CharacterEscapeEncoder, которая ничего не ускользнет.
Marshaller m = jcb.createMarshaller();
m.setProperty(
"com.sun.xml.bind.marshaller.CharacterEscapeHandler",
new NullCharacterEscapeHandler());
С
public class NullCharacterEscapeHandler implements CharacterEscapeHandler {
public NullCharacterEscapeHandler() {
super();
}
public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
writer.write( ch, start, length );
}
}
Ответ 12
По какой-то причине у меня нет времени, чтобы узнать, это сработало для меня при настройке
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
В отличие от использования "UTF-8"
или "Unicode"
Я предлагаю вам попробовать их, и, как @Javatar сказал, проверьте их сброс в файл, используя:
marshaller.marshal(shipOrder, new File("<test_file_path>"));
и открыть его с помощью достойного текстового редактора, например notepad ++