【问题标题】:JAXB , Unmarshalling and Marshalling against a Wrapper class.JAXB ,针对 Wrapper 类的解组和编组。
【发布时间】:2016-01-05 11:56:04
【问题描述】:

我完全是 JAXB 架构的新手。但这是我想要做的事情,简而言之就是卡在哪里。

我正在创建一个 web 应用程序,客户端将首先注册他的 xsd,然后根据 xsd 发送他的 xml/json 数据。

对于 xsd 的注册,我使用的是 XJC(不是作为 maven 插件,而是来自 java 代码本身:

 SchemaCompiler sc = XJC.createSchemaCompiler();
    File schemaFile = new File(schemaPath);
    InputSource is = new InputSource(new FileInputStream(schemaFile));
    is.setSystemId(schemaFile.getAbsolutePath());
    sc.parseSchema(is);
    S2JJAXBModel model = sc.bind();
    JCodeModel jCodeModel = model.generateCode(null, null);
    jCodeModel.build(new File(outputDirectory));

按 XSD 的样子:

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

    <xsd:element name="Metadata" type="Metadata" />

    <xsd:complexType name="Metadata">
        <xsd:sequence>

            <xsd:element name="MicroscopeStagePosition"
                type="MicroscopeStagePosition" maxOccurs="1" minOccurs="1">
            </xsd:element>

        </xsd:sequence>
    </xsd:complexType>


    <xsd:complexType name="MicroscopeStagePosition">
        <xsd:sequence>
            <xsd:element name="Start" type="xsd:string"/>
            <xsd:element name="End" type="xsd:string"/>
        </xsd:sequence>
   </xsd:complexType> 
   </xsd:schema>

我正在从上面创建带有 JAXB 注释的 POJO 类,创建的 2 个类是:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Metadata", propOrder = {
    "microscopeStagePosition"
})
public class Metadata {

    @XmlElement(name = "MicroscopeStagePosition", required = true)
    protected MicroscopeStagePosition microscopeStagePosition;

    public MicroscopeStagePosition getMicroscopeStagePosition() {
        return microscopeStagePosition;
    }
    public void setMicroscopeStagePosition(MicroscopeStagePosition value) {
        this.microscopeStagePosition = value;
    }

}

还有

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MicroscopeStagePosition", propOrder = {
    "start",
    "end"
})
public class MicroscopeStagePosition {

    @XmlElement(name = "Start", required = true)
    protected String start;
    @XmlElement(name = "End", required = true)
    protected String end;

    public String getStart() {
        return start;
    }

    public void setStart(String value) {
        this.start = value;
    }

    public String getEnd() {
        return end;
    }

    public void setEnd(String value) {
        this.end = value;
    }

}

现在我的想法是有一个通用的带注释的类,它将包装上述实时创建的类(这个类是真实创建的,因此可以有任何需要的东西)。

问题是我不知道哪个 xsd 会出现,因此 rootelement 不会有帮助。所以我想围绕创建的 JAXB 类创建一个包装器,然后在所有 API 中只处理这个包装器类。

我已经实时创建了以下类:

public class MyModel {
@XmlElement(required = true)
protected Metadata Metadata;
@XmlElement(required = true)
protected MicroscopeStagePosition MicroscopeStagePosition;
}

是否可以基于此包装类解组传入的 XML。请注意,不能强制传入的 XML 在其中包含 MyModel 的根元素。所以我尝试创建根 JAXBElement,然后将其分配给包装类:

  MyModel je = new MyModel();

JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {MyModel.class}, null);

         Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

         InputStream is = new ByteArrayInputStream(sIncomingMetadataXML.getBytes());

        JAXBElement<MyModel> root = jaxbUnmarshaller.unmarshal(new StreamSource(
                is), MyModel.class);
        je = root.getValue();

如果我用 @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) 注释 MyModel 并从我的 api 返回 je,它是一个 null 子对象 xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyModel/>

如果没有,则会出现错误:

Java 类 a 和 MIME 媒体类型的消息正文编写器 未找到应用程序/xml。

那么我可以像上面那样创建一个包装器类吗?如果可以的话怎么做?或者我在这里完全错过了一些东西

【问题讨论】:

  • 请注意,不能强制传入的 XML 在其中包含 MyModel 的根元素。为什么不呢?,似乎是最简单的方法.... 存储传入的 xml(添加您需要的内容)然后解组,您可以在运行时执行此操作(无需保存到文件)....
  • 嗯,我认为这将是干净的代码,但你能详细说明如何在不保存到文件的情况下将父标签添加到传入的 XML 中吗?
  • 我已经发布了一个答案,我经常这样做,因为当我与来自 java 的不同服务(msxml ecc)交互时,我需要处理不同的 BOM 标头 ecc。也许它需要更多的内存,但你可以更好地控制传入的数据......
  • 另一种解决方案是覆盖解组行为,但这个我会留给你......

标签: xml xsd jaxb marshalling unmarshalling


【解决方案1】:

不考虑 “请注意,不能强制传入的 XML 在其中包含 MyModel 的根元素”,因为用户已在评论中批准。

不是将流直接传递给 Jaxb,而是读入 StringBuffer,我经常这样做以处理不同的 UTF 标头,按照我喜欢的 ecc 记录。

在你的情况下添加迫切需要的标签。

  1. 将流读入StringBuffer sb(参见示例Read/convert an InputStream to a String

  2. StringBuffer中根据需要插入标签

  3. 解组器StringBuffer

    StringReader reader = new StringReader(sb.toString());
    JAXBElement<MyModel> root = getUnmarshaller().unmarshal(reader)
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-24
    • 2016-01-26
    • 2010-10-11
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    相关资源
    最近更新 更多