使用 @XmlPath 和 jaxb/MOXy 来映射复杂类型

2023-12-08

我有一个深层 XML 结构,其中有许多无意义的包装器,我将其映射到单个 Java 类。使用 @XmlPath 映射简单的数据类型就像在公园散步,但是当涉及到实际需要自己的类的类型时,我不太确定如何做到这一点,特别是当这些类型也应该放入列表中时。

我在绘制所有地图时遇到问题element在下面的示例中输入我的Element班级。自从elements包装器驻留在使用映射的资源中@XmlPath我无法使用@XmlElementWrapper,否则我通常会这样做。

XML 结构示例

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <s:resource>
        <s:information>
            <s:date>2013-07-04</s:date>
            <s:name>This example does not work</s:name>
        </s:information>
        <s:elements>
            <s:refobj>
                <s:id>1</s:id>
                <s:source>First Source</s:source>
            </s:refobj>
            <s:refobj>
                <s:id>2</s:id>
                <s:source>Second Source</s:source>
            </s:refobj>
            <s:refobj>
                <s:id>5</s:id>
                <s:source>Fifth Source</s:source>
            </s:refobj>
        </s:elements>
    </s:resource>
</s:root>

根.java

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlPath("resource/information/date/text()")
    private String date;

    @XmlPath("s:resource/s:information/s:name/text()")
    private String name;

    @XmlPath("resource/elements/refobj")
    private List<RefObj> refObjs;

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

RefObj.java

@XmlRootElement(name = "refobj")
@XmlAccessorType(XmlAccessType.FIELD)
public class RefObj {

    @XmlElement(name = "id")
    private int id;

    @XmlElement(name = "source")
    private String source;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

}

编组器/解组器

public static void main(String[] args) {
    String xml = getXML();

    Root root = null;
    try {
        JAXBContext context = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        StringReader stringReader = new StringReader(xml);

        root = (Root) unmarshaller.unmarshal(stringReader);
    } catch (Exception ex) {
        System.err.println("Failed to unmarshal XML!");
    }

    try {
        JAXBContext context = JAXBContext.newInstance(Root.class);
        Marshaller marshaller = context.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.eu/test ResourceSchema.xsd");

        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(root, stringWriter);

        System.out.println(new String(stringWriter.toString().getBytes(Charset.forName("UTF-8"))));
    } catch (Exception ex) {
        System.err.println("Failed to marshal object!");
    }

}

包信息.java

@XmlSchema(
        namespace = "http://www.example.eu/test",
        attributeFormDefault = XmlNsForm.QUALIFIED,
        elementFormDefault = XmlNsForm.QUALIFIED,
        xmlns = {
    @XmlNs(
            prefix = "s",
            namespaceURI = "http://www.example.eu/test")
},
        location = "http://www.example.eu/test ResourceSchema.xsd")
package se.example.mavenproject1;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

我可以执行该应用程序,但当我解组/编组 XML 内容时,没有映射任何元素,而是得到仅包含信息的 XML 表示形式。

Update

在发布前面的示例后,我意识到它实际上按预期工作,这让我更加困惑。尽管我尝试在生产代码中复制(以前的)工作示例,但没有成功,但我已经设法将我遇到的问题实际引入到示例代码中。由于我需要添加一个命名空间来解决问题,因此我假设它与命名约定和 X(ml)Path 有关。

我还添加了package-info.java以及我在处理这些对象时使用的编组器/解组器。由于 jaxb.properties 不包含任何令人兴奋的内容,因此我将其省略。


当我运行你的示例时,一切正常。由于您的真实模型可能具有 get/set 方法,因此您需要确保添加@XmlAccessorType(XmlAccessType.FIELD)否则 MOXy(或任何其他 JAXB impl)也会将相应的属性视为已映射(请参阅:http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).

import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlPath("resource/information/date/text()")
    private String date;

    @XmlPath("resource/information/name/text()")
    private String name;

    @XmlPath("resource/elements/element")
    private List<Element> elements;

}

您还需要确保您拥有jaxb.properties文件与您的域模型位于同一包中,并使用以下条目将 MOXy 指定为您的 JAXB 提供程序(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

了解更多信息

  • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html

更新#1

当您的文档具有命名空间限定时@XmlPath注释需要考虑到这一点。路径中的节点可以根据@XmlSchema注解。

包信息

In your package-info对前缀进行分类s分配给命名空间 URIhttp://www.example.eu/test.

@XmlSchema(
        namespace = "http://www.example.eu/test",
        attributeFormDefault = XmlNsForm.QUALIFIED,
        elementFormDefault = XmlNsForm.QUALIFIED,
        xmlns = {
    @XmlNs(
            prefix = "s",
            namespaceURI = "http://www.example.eu/test")
},
        location = "http://www.example.eu/test ResourceSchema.xsd")
package se.example.mavenproject1;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

Root

这意味着符合条件的节点http://www.example.eu/test命名空间应该有前缀s in the @XmlPath注解。

import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlPath("s:resource/s:information/s:date/text()")
    private String date;

    @XmlPath("s:resource/s:information/s:name/text()")
    private String name;

    @XmlPath("s:resource/s:elements/s:element")
    private List<Element> elements;

}

更新#2

所以看起来好像需要在@XmlPath中指定命名空间 将路径映射到复杂对象时,但可以在以下情况下跳过 将路径映射到简单对象,例如字符串或整数。

这是一个错误。您应该命名空间限定@XmlPath对于简单对象的处理方式与对于复杂对象的处理方式相同(请参阅更新#1)。正确的映射今天可以正常工作,我们将修复以下错误,以便不正确的映射能够正确运行。您可以使用下面的链接来跟踪我们在该问题上的进展:

  • http://bugs.eclipse.org/412311
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 @XmlPath 和 jaxb/MOXy 来映射复杂类型 的相关文章

随机推荐

  • 50 次迭代后,常数“pi”的近似值并没有变得更好

    在 R 中我写了这个函数 ifun lt function m o c for k in 1 m o k prod 1 k prod 2 1 k 1 o sum 2 1 sum o Final result print o sum 该函数近
  • Android Room:使用 Room 插入关系实体

    我在 Room 中添加了一对多关系Relation 我提到这个帖子在 Room 中为关系编写以下代码 这篇文章讲述了如何从数据库读取值 但将实体存储到数据库中会导致userId为空意味着这两个表之间没有关系 我不确定什么是理想的方式inse
  • 管理员访问白名单IP地址

    我的网站上有一个区域 我只想允许少数人访问 我的代码现在仅适用于一个 IP 地址 但我希望能够添加更多 这是我正在使用的 ipaddress SERVER REMOTE ADDR if ipaddress 111 111 111 111 A
  • OpenGL 旋转 - 局部轴与全局轴

    因此 我尝试根据偏航 俯仰和滚动方案旋转一个对象 相对于该对象自己的局部轴而不是全局空间的轴 根据this 我需要按该顺序执行轮换 我将其解释为 glRotatef m Rotation y 0 0 1 0 0 0 glRotatef m
  • Cordova chrome.socket API。有什么例子吗?

    我正在尝试使用 org chromium socket 插件 但我找不到很多例子 这是我的代码 var connButton document getElementById connButton connButton addEventLis
  • 标准 TFlite 对象检测模型在 MLKit 中不起作用

    如果我使用预训练的 TFLite 对象检测模型在 MLKit 中 我收到以下错误 CalculatorGraph Run failed in Run Calculator Open for node BoxClassifierCalcula
  • 如何离开办公室使用另一个邮箱

    我正在尝试使用 EWS EWS 托管 API 2 0 获取给定邮箱的 离开办公室 设置 设置如下 单个 服务帐户 邮箱 可读取其他邮箱日历和外出设置 使用 EWS 托管 API 可以轻松完成日历部分 但我似乎无法弄清楚如何使用 API 获取
  • 将 jquery 数据表导出到带有附加行的 Excel 不起作用 IE

    我正在尝试使用 jquery 导出按钮选项将数据表导出到 Excel 工作表 我希望在 Excel 文件中的表数据之前添加额外的行 我在小提琴中做了一个类似的演示https jsfiddle net xevpdeo1 17 它在 Chrom
  • 以编程方式将文件夹添加到 Finder 中的“位置”

    我正在尝试弄清楚如何以编程方式将文件夹添加到 Finder 的 位置 侧边栏 我已经看到了通过 Finder 首选项修改它的方法 但我也看到一些应用程序实际上将文件夹添加到侧边栏 如果有人对我应该查找的内容有任何建议 指示 我将不胜感激 这
  • 从向量对中获取值时出错

    为什么在访问对向量的迭代器中对的值时会出现以下错误 vector lt pair
  • 使用 php 从非公共 html 文件夹下载文件

    我有许多文件存储在服务器上 但不在 public html 目录中 这个想法是 登录的用户可以下载文件 使用 SESSION 变量来检查他们是否登录 但如果其他人使用他们的计算机 他们就无法在浏览器历史记录中看到直接文件路径 即使他们这样做
  • Gluon Mobile 项目不适用于 gradle 6

    我有一个 Gluon 移动项目 其 build gradle 如下所示 buildscript repositories jcenter google mavenCentral maven url http nexus gluonhq co
  • 如何从 R 中的流式 MapReduce 作业获取文件名?

    我正在流式处理 R mapreduce 作业 并且需要获取文件名 我知道 Hadoop 在当前作业启动之前设置环境变量 并且我可以使用 Sys getenv 访问 R 中的环境变量 我发现 获取流式hadoop程序中的输入文件名 和 Sys
  • 正交船体算法

    我正在尝试找到一种方法来确定直线多边形来自一组整数点 由下图中的红点表示 下图显示了我想要实现的目标 1 我只需要定义直线多边形边界的最小点集 我能找到的大多数船体算法都不满足这个问题的正交性质 例如礼物包装算法 产生以下结果 即not我想
  • 哈斯克尔:记忆化

    在离开多年并忘记一切之后 我正在尝试重新学习 Haskell 但我发现自己仍然感到困惑记忆化 特别是 我正在尝试编写一个程序来生成混乱的数量D n of n对象 原始位置没有任何项目的排列 号码D n 可以递归地定义为D 1 0 D 2 1
  • OpenCV 3.0 线迭代器

    我想使用线迭代器在使用 Python 的 OpenCV 3 0 中 为 Python 构建的 OpenCV 3 0 仍然可用吗 看来网上的答案都指向cv InitLineIterator这是cv模块 我尝试导入此模块 但似乎它不包含在当前版
  • 使用 Kubernetes 部署并通过 Ingress 连接后 SSE 损坏

    我有一个使用 EventStream 的 ReactJS 客户端和一个实现 SSE 的 golang 后端 当我将浏览器连接到在 localhost 上运行的后端时 以及当我的后端在带有端口转发的 k8s 上运行时 一切似乎都正常 一旦我使
  • 在 Java 中使用 XSOM 解析 XSD 架构。如何访问元素和复杂类型

    我在使用 Java 中的 XSOM 解析 XSD 文件时遇到了很多困难 我有两个 XSD 文件 一个定义日历 第二个定义全局类型 我希望能够读取日历文件并确定 日历有 3 个属性 有效的是一个名为 eYN 的 ENUM Cal 是一个字符串
  • 从 Java/ Android 线程返回值

    我的 android 类中有以下线程 如何从线程中获取 err 的值 public int method new Thread new Runnable int err Override public void run err device
  • 使用 @XmlPath 和 jaxb/MOXy 来映射复杂类型

    我有一个深层 XML 结构 其中有许多无意义的包装器 我将其映射到单个 Java 类 使用 XmlPath 映射简单的数据类型就像在公园散步 但是当涉及到实际需要自己的类的类型时 我不太确定如何做到这一点 特别是当这些类型也应该放入列表中时