【问题标题】:Is there a a way to add a wrapper element during the marshalling in JAXB for non collection element?有没有办法在 JAXB 编组期间为非集合元素添加包装器元素?
【发布时间】:2021-07-19 12:03:11
【问题描述】:

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

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

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

从示例 XML 中可以看出,carinfo 标签是元素 engineyear 的外部(包装)标签,但 carInfo 标签不存在于 Parent 或 @987654332 中@ 班级。由于这些是标准类,我无法修改字段/添加新字段。因此,我想使用 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);
     }
     
     
}

【问题讨论】:

  • 您好,可以添加 input.json 吗?
  • @dariosicily 很抱歉错过了添加Json。我现在加了。请检查。从 JSON 中可以看出,我没有 carInfo 标签,但在 XML 中我想添加 carInfo 标签。有没有办法可以将class 中不存在的附加标签添加到我的XML
  • 除非你修改你的类,否则我的建议是通过 jaxb 来做这件事,即使丑陋的是操纵 xml 树以获得所需的结果。
  • 非常感谢您的时间和回复。实际上,这是可能的,我能够找到解决方法。我在这里发布了一个问题:stackoverflow.com/questions/67300882/… 现在我正试图找出一种方法将其设为XML Adapter,而不是将其作为类中的方法。
  • 感谢您的链接,同时我找到了一个可能的解决方案,使用 xsl 文件而不修改原始类,所以如果您有兴趣,我会提交答案。

标签: java xml jaxb marshalling


【解决方案1】:

最后,我能够使用来自Moxy@XmlPath 获得它,它是基于Jaxb 的库。您可以将@XmlPath 用于任何元素,例如集合、非集合、字符串等。我花了很多时间尝试配置和解决问题,因此在此处发布答案,以便对未来,他们没有我这么多时间:)

请寻找配置Moxyhere的答案

另外,请参阅如何使用 @XmlPath here 获取 XML 的包装器元素

您还可以在EclipseLink 文档中阅读更多相关信息。

【讨论】:

    【解决方案2】:

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

    template.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 a Transformer 并将新的 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);
    

    【讨论】:

    • 有趣的方法。感谢您提供另一种创作方式。然而,当 XML 有点复杂并且不断变化时,管理这些文件可能会有点棘手。因此,我觉得在课堂上处理它是一种简单的方法。但这个解决方案可能对将来的某人有所帮助。
    • @BATMAN_2008 不客气,我同意你的观点,如果类可以修改,那么使用它们会更容易。 XML 案例很简单,因此 xsl 在线生成器无需任何修改即可使用所需的文件。
    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多