JAXB Marshaller:StringWriter输出具有截断的标记值

时间:2012-08-27 16:58:29

标签: java-ee jaxb

我想将java对象编组为xml字符串。 因此,我获得了一个模式,我可以从中生成JAXB类。 有一个set方法(对应于模式中的hexbinary类型的元素),我必须设置一个字符串。 字符串大小约为2566。 通过setter方法将数据设置到对象后,我调用marshaller传递stringWriter参数。

但是在打印stringWriter时,我发现它被截断了。我没有看到整个2566个字符。

有什么问题?有什么想法吗?

感谢名单!

更新

我想我发现了这个问题。我必须找到合适的标题,因为我的问题推理错误!问题如下: 我的架构中有一个“hexbinary”元素。生成的类具有相应的set / get方法。要设置值,我使用了apache commons包的HexEncodeString方法,并意识到marshaller在hexbinary标签中显示36383639字符串“hi”,其实际的Hex编码是6869 :(因此,问题是编组后的xml有一个标签使用大于原始字符的字符数的值,而不是像我之前想象的那样被截断!

感谢 Blaise Doughan 的代码。我修改了它并重现了这个问题。

首先是一个示例模式:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="Root">
    <xs:sequence>
      <xs:element name="string" type="xs:string" minOccurs="0"/>
            <xs:element name="a" type="xs:hexBinary" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

有了这个,我生成了ObjectFactory类和Root类。 我不得不修改ObjectFactory类以包含JAXBElement,以便我可以将它传递给Marshaller。有了这些,我参加了Blaise Doughan的Demo课程并将其修改为:

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);      

    // The object factory
    ObjectFactory objFactory = new ObjectFactory();
    Root root = new Root();
    String str = new String("hi");
    String val = Hex.encodeHexString(str.getBytes());
    root.setString(str);
    root.setArr(val.getBytes());

        System.out.println("val="+val);
        System.out.println("getString ="+root.getString());
        System.out.println("getArr="+new String(root.getArr()));

        // Marshal the object to a StringWriter
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(objFactory.createRoot(root),stringWriter);
//      marshaller.marshal(root, stringWriter);

        // Convert StringWriter to String
        String xml = stringWriter.toString();
        System.out.println(xml);

        // Unmarshal the XML and check length of long String
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println(root.getString().length());
        System.out.println(root.getString());
        System.out.println(new String(root.getArr()).length());
        System.out.println(new String(root.getArr()));
    }

}

我得到的输出是:

val=6869
getString =hi
getArr=6869
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:Root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:ns3="http://example.com/root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <string>hi</string>
    <arr>36383639</arr>
</ns3:Root>

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://example.com/root", local:"Root"). Expected elements are (none)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:631)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:236)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:231)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1038)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:467)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:448)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:626)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3103)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:922)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)
    at example.Demo.main(Demo.java:43)

为什么arr标记为36383639而不是6869?

1 个答案:

答案 0 :(得分:1)

新答案

在示例代码中,valstr.getBytes()的hexBinary表示形式。但是,您在arr属性上设置的值是十六进制编码的字符串中的字节。

String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(val.getBytes());

我相信你的意思是:

String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(str.getBytes());

将产生以下输出

val=6869
getString =hi
getArr=hi
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <string>hi</string>
    <a>6869</a>
</root>

换句话说

    String str = new String("hi");
    System.out.print("String:  " + str);
    System.out.println(" hexBinary:  " + Hex.encodeHexString(str.getBytes()));
    String val = Hex.encodeHexString(str.getBytes());
    System.out.print("String:  " + val);
    System.out.println(" hexBinary:  " + Hex.encodeHexString(val.getBytes()));

将输出:

String:  hi hexBinary:  6869
String:  6869 hexBinary:  36383639

原始回答

我无法重现您所看到的问题。我使用String大小的500000。以下是我的尝试(这个样本适合你?)。是否有可能截断是由于您正在将长字符串写入控制台?

<强>演示

package forum12146217;

import java.io.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        // Build a long String
        StringBuilder stringBuilder = new StringBuilder();
        for(int x=0; x<500000; x++) {
            stringBuilder.append("a");
        }
        Root root = new Root();
        root.setString(stringBuilder.toString());
        System.out.println(root.getString().length());

        // Marshal the object to a StringWriter
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(root, stringWriter);

        // Convert StringWriter to String
        String xml = stringWriter.toString();
        //System.out.println(xml);

        // Unmarshal the XML and check length of long String
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println(unmarshalledRoot.getString().length());
    }

}

<强>根

package forum12146217;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private String string;

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

}

<强>输出

500000
500000