2010-06-11 7 views
12

ich entschuldige mich, wenn diese beantwortet wurde, aber die Suchbegriffe Ich habe mit (dh JAXB @XmlAttribute kondensiert oder JAXB XML Marschall String unterschiedliche Ergebnisse) kommen mit nichts auf.JAXB Marschälle XML anders vs. String zu Output

ich JAXB bin mit der UN/Marschall-Objekte mit @XmlElement und @XmlAttribute Anmerkungen kommentiert. Ich habe eine Formatierungsklasse, die zwei Methoden bietet - eine umschließt die Marshal-Methode und akzeptiert das zu marshallende Objekt und eine OutputStream, die andere akzeptiert das Objekt und gibt die XML-Ausgabe als String zurück. Leider bieten diese Methoden nicht dieselbe Ausgabe für dieselben Objekte. Wenn in einer Datei Marshalling, einfache Objektfelder intern mit @XmlAttribute markiert sind, gedruckt wie:

<element value="VALUE"></element> 

während, wenn in einen String Marshalling, sie sind:

<element value="VALUE"/> 

Ich würde das zweite Format für beide Fälle bevorzugen , aber ich bin neugierig, wie ich den Unterschied kontrollieren kann, und ich würde mich damit begnügen, dass sie immer gleich sind. Ich habe sogar einen statischen Marshaller erstellt, den beide Methoden verwenden, um verschiedene Instanzwerte zu eliminieren. Die Formatierungscode folgt:

/** Marker interface for classes which are listed in jaxb.index */ 
public interface Marshalable {} 

/** Local exception class */ 
public class XMLMarshalException extends BaseException {} 

/** Class which un/marshals objects to XML */ 
public class XmlFormatter { 
    private static Marshaller marshaller = null; 
    private static Unmarshaller unmarshaller = null; 

    static { 
     try { 
      JAXBContext context = JAXBContext.newInstance("path.to.package"); 
      marshaller = context.createMarshaller(); 
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
      marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); 

      unmarshaller = context.createUnmarshaller(); 
     } catch (JAXBException e) { 
      throw new RuntimeException("There was a problem creating a JAXBContext object for formatting the object to XML."); 
     } 
    } 

    public void marshal(Marshalable obj, OutputStream os) throws XMLMarshalException { 
     try { 
      marshaller.marshal(obj, os); 
     } catch (JAXBException jaxbe) { 
      throw new XMLMarshalException(jaxbe); 
     } 
    } 

    public String marshalToString(Marshalable obj) throws XMLMarshalException { 
     try { 
      StringWriter sw = new StringWriter(); 
      return marshaller.marshal(obj, sw); 
     } catch (JAXBException jaxbe) { 
      throw new XMLMarshalException(jaxbe); 
     } 
    } 
} 

/** Example data */ 
@XmlType 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Data { 

    @XmlAttribute(name = value) 
    private String internalString; 
} 

/** Example POJO */ 
@XmlType 
@XmlRootElement(namespace = "project/schema") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Container implements Marshalable { 

    @XmlElement(required = false, nillable = true) 
    private int number; 

    @XmlElement(required = false, nillable = true) 
    private String word; 

    @XmlElement(required = false, nillable = true) 
    private Data data; 
} 

Die r eiter marshal(container, new FileOutputStream("output.xml")) und marshalToString(container) Aufruf sind wie folgt:

Ausgabe

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:container xmlns:ns2="project/schema"> 
    <number>1</number> 
    <word>stackoverflow</word> 
    <data value="This is internal"></data> 
</ns2:container> 

und

Ausgabe auf String

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:container xmlns:ns2="project/schema"> 
    <number>1</number> 
    <word>stackoverflow</word> 
    <data value="This is internal"/> 
</ns2:container> 
+0

Danke, dass für die Reinigung ein wenig, hatte ich Schwierigkeiten nicht den XML interpretiert hat. – Andy

+0

Weitere Untersuchungen haben gezeigt, dass ich nach der Möglichkeit suche zu kontrollieren, ob JAXB "leere Elemente" in HTML (gepaarte Tags) oder XML (Single Tag) schreibt. In anderen JAXB-Anbietern wie JaxMe ist dies eine Eigenschaft, die gesetzt werden kann, aber anscheinend nicht in JAXB. Ich frage mich nur, warum es je nach Zieltyp unterschiedlich ist. Ich weiß, dass sie funktional gleichwertig sind, aber ich brauche sie, um mit unserem System zu arbeiten. Irgendwelche Ideen? – Andy

Antwort

8

Sieht aus wie dies ein "Bug" in JAXB sein könnte.Mit Blick auf die Quelle, erstellen die Anrufe für Marschall() verschiedene Autoren basierend auf der Ausgabe/Schreiber Typ Parameter:

public void marshal(Object obj, OutputStream out, NamespaceContext inscopeNamespace) throws JAXBException { 
    write(obj, createWriter(out), new StAXPostInitAction(inscopeNamespace,serializer)); 
} 

public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException { 
    write(obj, XMLStreamWriterOutput.create(writer,context), new StAXPostInitAction(writer,serializer)); 
} 

Die Implementierungen der Autoren unterscheidet sich in Bezug auf ihren Umgang mit „leeren Elemente“. Der obige Code stammt von:

jaxb-ri \ runtime \ src \ com \ sun \ xml \ bind \ v2 \ runtime \ MarshallerImpl.java.

Die beiden Autoren Sie erstellen sind:

jaxb-ri \ runtime \ src \ com \ Sonne \ xml \ bind \ v2 \ runtime \ output \ UTF8XmlOutput.java

jaxb-ri \ runtime \ src \ com \ sun \ xml \ bind \ v2 \ runtime \ output \ XMLStreamWriterOutput.java

+4

Genauer gesagt ist dies ein Fehler in der Metro JAXB-Implementierung. Andere JAXB-Implementierungen wie EclipseLink JAXB (MOXy) haben diesen Fehler nicht. –

1

Ich weiß nicht, warum JAXB Datei tut dies - oder auch wenn es JAXB ist - wenn JAXB du bist Wenn XML beispielsweise über einen SAXContentHandler übergeben wird, hat es keine direkte Kontrolle darüber, wie nahe Tags erzeugt werden.

Um konsistentes Verhalten zu erhalten, könnten Sie Ihren OutputStream in einen OutputStreamWriter, z.

Entlang der gleichen Zeilen sehen Sie möglicherweise, was passiert, wenn Sie den StringWriter in einem PrintWriter umbrechen. Vielleicht gibt es einen benutzerdefinierten Code, der StringWriter erkennt, um den Ausgang so kurz wie möglich zu halten. Klingt unwahrscheinlich, aber ich habe keine andere Erklärung.

+0

Ich habe genau das gemacht, bevor ich hier wieder nachgesehen habe und konsistente Ergebnisse bekommen habe. Vielen Dank. – Andy

0

Warum ist es wichtig? < Tag-Attribut = "Wert"> </tag> entspricht < Tag-Attribut = "Wert" /> in xml

+0

Ich verstehe, dass sie funktional gleichwertig sind, aber es gibt Idiosynkrasien innerhalb der Anwendung, die ich kodiere, die lexikographisch identische Ausgabe erfordern. – Andy

2

Die gute Nachricht ist, dass JAXB eine Spezifikation mit mehr als einer Implementierung ist (genau wie JPA). Wenn eine Implementierung ist nicht Ihre Bedürfnisse zu erfüllen, andere sind wie Eclipse JAXB (moxy):

+0

In der Tat, da diese Verbindung jetzt nicht mehr besteht –