首页 > 解决方案 > 有没有一种方法可以在 JAXB 编组期间为非集合元素添加包装器元素?

问题描述

我正在尝试使用库中的marshaling方法创建 XML JAXB。对于这种方法,我使用标准的 java 类并将注解分配给它。我想为类中的某些元素添加一个包装器元素,这些元素不是Collections.

我知道@XmlElementWrapper哪些可以用于Collections但我没有收藏。我有一些元素,我希望有一个外部 XML 元素,以便它可以匹配标准 XSD。

我只是想知道是否有一种方法可以将外部 XML 元素添加到某些元素,以便创建 XML 匹配标准 XSD 格式。如果没有直接的方法,那么我可以采取什么替代方法?

正如我们从示例 XML 中看到的那样,carinfo标签是元素的外部(包装)标签,engineyearcarInfo标签不存在于ParentorChild类中。由于这些是标准类,我无法修改字段/添加新字段。因此,我想使用 JAXB 处理包装器 XML 标记添加。

以下是输入 JSON:

{
   "brand": "Ferari",
   "build": "Italy",
    "engine": "Mercedes",
    "year": "2021"
   
}

以下是我想要的输出 XML:

<?xml version="1.0"?>
<Car>
    <brand>Ferari</brand>
    <build>Italy</build>
    <carinfo>
        <engine>Mercedes</engine>
        <year>2021</year>
    </carinfo>
</Car>

以下是我的课程:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
@XmlType(name = "Parent")
public class Parent{
    private String brand;
    private String year;
    
    //Getters and Setters avoided
}

基于创建 XML 的类:

@XmlRootElement(name = "Car")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Child",propOrder={"brand","engine","build","year"})
public class Child extends Parent{
    private String engine;
    private String build;
    
    //Getter and Setters avoided
}

将创建 XML 的主类:我正在使用该Jackson库从Json文件中读取值并基于Jaxb注释创建 XML。

public class Main{

     public static void main(String []args){
        JsonFactory jsonFactory = new JsonFactory();
        JsonParser jsonParser = jsonFactory.createParser(new File(Main.class.getClassLoader().getResource("input.json").toURI()));
        Child eventInfo = jsonParser.readValueAs(Child.class);
        JAXBContext context = JAXBContext.newInstance(Child.class);
        Marshaller mar = context.createMarshaller();
        mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        mar.marshal(eventInfo, System.out);
     }
     
     
}

标签: javaxmljaxbmarshalling

解决方案


从我的角度来看,可以在您的 xml 中包含一个新标签,使用和api的组合保留原始类。首先是为转换创建一个 xsl 样式表文件,如下所示:jaxbjavax.xml.transform

模板.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Car>
<brand>
<xsl:value-of   select="/Car/brand"/>
</brand>
<build>
<xsl:value-of   select="/Car/build"/>
</build>
<carinfo>
<engine>
<xsl:value-of   select="/Car/engine"/>
</engine>
<year>
<xsl:value-of   select="/Car/year"/>
</year>
</carinfo>
</Car>
</xsl:template>
</xsl:stylesheet>

然后你可以使用 set aTransformer并传递给它一个新的JAXBSource,如下所示:

Child eventInfo = jsonParser.readValueAs(Child.class);
JAXBContext context = JAXBContext.newInstance(Child.class);
           
// Create Transformer
TransformerFactory tf = TransformerFactory.newInstance();
StreamSource xslt = new StreamSource(xslFile);
Transformer transformer = tf.newTransformer(xslt);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");

//Print to the stdout the desired xml with the new nested tag 
//including the two existing tags
StreamResult result = new StreamResult(System.out);
JAXBSource source = new JAXBSource(context, eventInfo);
transformer.transform(source, result);

推荐阅读