12

これが回答されている場合は申し訳ありませんが、私が使用している検索用語 (つまり、 JAXB @XmlAttribute condensedまたはJAXB XML marshal to String different results ) は何も思いつきません。

私は JAXB を使用して、注釈@XmlElement@XmlAttribute注釈が付けられたオブジェクトをアン/マーシャリングしています。2 つのメソッドを提供するフォーマッタ クラスがあります。1 つはマーシャル メソッドをラップし、マーシャルするオブジェクトをOutputStream受け入れます。残念ながら、これらのメソッドは同じオブジェクトに対して同じ出力を提供しません。ファイルにマーシャリングする場合、内部的に でマークされた単純なオブジェクト フィールドは次のように出力@XmlAttributeされます。

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

一方、文字列にマーシャリングする場合は次のようになります。

<element value="VALUE"/>

私はどちらの場合も 2 番目の形式を好みますが、違いをどのように制御するかについて興味があり、関係なく同じであることに満足しています。両方のメソッドが異なるインスタンス値を排除するために使用する 1 つの静的マーシャラーも作成しました。書式設定コードは次のとおりです。

/** 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;
}

marshal(container, new FileOutputStream("output.xml"))とを呼び出した結果はmarshalToString(container)次のとおりです。

ファイルへの出力

<?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>

文字列に出力

<?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>
4

3 に答える 3

8

これはJAXBの「バグ」のようです。ソースを見ると、marshal()の呼び出しは、出力/ライタータイプパラメーターに基づいて異なるライターを作成します。

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

ライターの実装は、「空の要素」を処理する方法に関して異なります。上記のコードは次のものです。

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

作成している2人のライターは次のとおりです。

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

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

于 2010-06-12T22:39:47.040 に答える
2

幸いなことに、JAXB は (JPA と同様に) 複数の実装を持つ仕様です。1 つの実装がニーズを満たしていない場合は、EclipseLink JAXB (MOXy) などの他の実装を利用できます。

于 2010-07-05T16:52:33.973 に答える
1

JAXBがこれを行っている理由がわかりません(またはJAXBであっても)。たとえば、JAXBがSAXContentHandlerを介してXMLを出力している場合、タグの生成方法を直接制御することはできません。

一貫した動作を得るには、OutputStreamをOutputStreamWriterでラップすることができます。

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

同じように、StringWriterをPrintWriterでラップするとどうなるかがわかるかもしれません。StringWriterたぶん、出力をできるだけ短くしようとすることを検出するカスタムコードがいくつかあります。ありそうもないように聞こえますが、他に説明はありません。

于 2010-06-11T23:01:05.980 に答える