Java序列化和反序列化

6

Employee.xsd

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0" elementFormDefault="qualified">
<xsd:include schemaLocation="Family.xsd"/>
    <xsd:element name="NewFields">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="empFirstName" type="xsd:string" />
                <xsd:element name="empLastName" type="xsd:string" />
                <xsd:element name="family" type="FamilyFields" nillable="true" maxOccurs="unbounded" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

Family.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0" elementFormDefault="qualified">
<xsd:complexType name="FamilyFields">
        <xsd:sequence>
            <xsd:element name="relation" type="xsd:string" />
            <xsd:element name="firstName" type="xsd:string" />
            <xsd:element name="lastName" type="xsd:string"/>
        </xsd:sequence>
</xsd:complexType>  
</xsd:schema>

一个使用这两个架构的第三方应用程序会生成一个类似于以下的xml字符串 -
<NewFields>
    <empFirstName>Kevin</empFirstName>
    <empLastName>Smith</empLastName>
    <family>
        <FamilyFields>
            <relation>self</relation>
            <firstName>New Kevin</firstName>
            <lastName>New Smith</lastName>
        </FamilyFields>
        <FamilyFields>
            <relation>wife</relation>
            <firstName>Jennifer</firstName>
            <lastName>Smith</lastName>
        </FamilyFields>
    </family>
</NewFields>

第二个模式始终是固定的模式。
我的要求是解析关系标签,如果关系是“自我”,则需要用相应字段的firstName和lastName覆盖empFirstName和empLastName。
我该如何实现这一点?
编辑1:Employee.xsd是动态的,可以是任何东西。但Family.xsd是静态的,可以从任何其他xsd导入。
2个回答

5
一般的概述:(a) 映射您的XML模式文件,(b) 解组给定的XML,(c) 在内存中修改XML对象,最后 (d) 在任何地方编组已修改的对象

映射您的XML模式文件

@XmlRootElement(name = "FamilyFields") public class FamilyFields {

  @XmlElement public String relation;
  @XmlElement public String firstName;
  @XmlElement public String lastName;

  public FamilyFields() {}
}

@XmlRootElement(name = "NewFields") public class NewFields {

  @XmlElement public String empFirstName;
  @XmlElement public String empLastName;
  @XmlElementWrapper(name = "family")
  @XmlElement(name = "FamilyFields")
  public List<FamilyFields> familyFields;

  public NewFields() {}
}

如果你需要建议的话:请手动完成!使用XJC生成JAXB实体几乎永远不会输出你期望的内容,如果你没有非常简单的模式文件,它可能会耗费很多时间。

获取JAXBContextUnmarshallerMarshaller

JAXBContext context = JAXBContext.newInstance(NewFields.class, FamilyFields.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Marshaller marshaller = context.createMarshaller();
// set optional properties
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

处理传入的XML

// the XML content you gave
String xml = ...

StringReader reader = new StringReader(xml);
NewFields newFields = (NewFields) unmarshaller.unmarshal(reader);

// modify the unmarshalled data to your heart's content
newFields.empLastName = ...

// marshal the modified data anywhere you want
marshaller.marshal(newFields, System.out);

如果我的 XML 有一个 FamilyFields 数组,似乎它不起作用!此外,我看到上面的代码出现了一些异常...像是 -- javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"family")。期望元素是 (unknown)。 - jagamot
我已经复制粘贴了您的两个模式声明和测试XML,并且它们对我有效。如果您遇到“意外元素”异常,可能是您尝试取消编组/编组的XML具有XML命名空间声明。那可能是个问题。(如果您在某个地方发布您的XML,比如pastebin,我可以查看一下。) - Kohányi Róbert
顺便说一下,我在我的测试中使用了JAXB 2.2.4-1。 - Kohányi Róbert
你说得对,我忘记在FamilyFields类中添加XMLROOTElement注释了!谢谢! - jagamot

0
如果您有一个XSD文件,那么使用XML数据绑定来操作XML是最简单的。使用XSD文件,您可以创建类似于Java Bean的类来表示XSD文件。现在,您可以在Java类上使用getter和setter,然后输出XML。有许多XML数据绑定解决方案。尝试使用XML beans:

http://xmlbeans.apache.org/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接