from - unmarshal xml to java object




Posso forzare JAXB a non convertire "in & quot;, ad esempio, quando si esegue il marshalling su XML? (10)

Ho un oggetto che viene eseguito il marshalling in XML usando JAXB. Un elemento contiene una stringa che include virgolette ("). L'XML risultante ha " dove" esiste ".

Anche se questo è normalmente preferito, ho bisogno del mio output per abbinare un sistema legacy . Come posso forzare JAXB a NON convertire le entità HTML?

-

Grazie per le risposte. Tuttavia, non vedo mai il gestore di escape () chiamato. Puoi dare un'occhiata e vedere cosa sto facendo male? Grazie!

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's 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();
    }
}

-

L'output è questo:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<shiporder orderid="Order's ID">
    <orderperson>The woman said, &quot;How ya doin &amp; stuff?&quot;</orderperson>
</shiporder>

e come puoi vedere, la richiamata non viene mai visualizzata. (Una volta richiamato il callback, mi preoccuperò di farlo effettivamente fare quello che voglio.)

-


@ Elliot è possibile utilizzarlo per abilitare il marshaller ad accedere alla funzione characterEscape. È strano ma funziona se si imposta " Unicode " anziché "UTF-8". Aggiungi questo subito prima o dopo aver impostato la proprietà CharacterEscapeHandler.

marshaller.setProperty(Marshaller.JAXB_ENCODING, "Unicode");

Tuttavia , non essere sicuro solo controllando la tua console all'interno dell'IDE, poiché dovrebbe essere visualizzata a seconda della codifica dell'area di lavoro. È meglio controllarlo anche da un file del genere:

marshaller.marshal(shipOrder, new File("C:\\shipOrder.txt"));

Direi che il modo più semplice per farlo è scavalcare 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);
    }
});

Ho appena creato il mio gestore personalizzato come una classe come questa:

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("&", "&amp;").replace("<", "&lt;")
                .replace(">", "&gt;").replace("'", "&apos;")
                .replace("\"", "&quot;");

        }
        out.write(st);
        System.out.println(st);
    }

}

nel metodo marshaller chiama semplicemente:

marshaller.setProperty(CharacterEscapeHandler.class.getName(),
                new XmlCharacterHandler());

funziona bene


Ho controllato le specifiche XML. http://www.w3.org/TR/REC-xml/#sec-references dice "i documenti ben formati non hanno bisogno di dichiarare nessuna delle seguenti entità: amp, lt, gt, apos, quot." così sembra che il parser XML utilizzato dal sistema legacy non è conforme.

(So ​​che non risolve il tuo problema, ma è almeno bello poter dire quale componente è rotto).


Il modo più semplice, quando si utilizza l'implementazione Marshaller di Sun, è fornire la propria implementazione del CharacterEscapeEncoder che non sfugge a nulla.

    Marshaller m = jcb.createMarshaller();
m.setProperty(
    "com.sun.xml.bind.marshaller.CharacterEscapeHandler",
    new NullCharacterEscapeHandler());

Con

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

Per qualche motivo non ho tempo per scoprirlo, ha funzionato per me quando si imposta

marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");

Invece di usare "UTF-8" o "Unicode"

Ti suggerisco di provarli e, come ha detto @Javatar , controlla che eseguano il dumping nel file usando:

marshaller.marshal(shipOrder, new File("<test_file_path>"));

e aprendolo con un editor di testo decente come notepad++



Soluzione trovata dal mio compagno di squadra:

PrintWriter printWriter = new PrintWriter(new FileWriter(xmlFile));
DataWriter dataWriter = new DataWriter(printWriter, "UTF-8", DumbEscapeHandler.theInstance);
marshaller.marshal(request, dataWriter);

Invece di passare xmlFile a marshal (), passare il DataWriter che conosce sia la codifica sia un appropriato gestore di escape, se presente.

Nota: Poiché DataWriter e DumbEscapeHandler si trovano entrambi nel pacchetto com.sun.xml.internal.bind.marshaller, è necessario eseguire il bootstrap di javac.


ho trovato lo stesso problema ho risolto questo utilizzando xmlWriter nel file xmlWriter c'è un metodo isEscapeText () e setEscapeTest che è di default true se non si desidera la trasformazione tra <to & lt quella volta è necessario setEscapeTest (false); durante lo smistamento

JAXBContext jaxbContext = JAXBContext.newInstance(your class);
Marshaller marshaller = 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); // <----------------- this line
// Attach the writer to the filter
outFilter.setContentHandler(writer);
// marshalling
marshaller.marshal(piaDto, outFilter);
marshaller.marshal(piaDto, System.out);

questo cambiamento writer.setEscapeText (false); risolto il problema, spero che questo cambiamento ti sia di aiuto


interessante ma con le corde che puoi provare

Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(data, sw);
sw.toString();

almeno per me questo non sfugge alle citazioni





html-entities