【问题标题】:How to create Java objects from XML tags which are referring each other?如何从相互引用的 XML 标记创建 Java 对象?
【发布时间】:2011-12-02 15:41:55
【问题描述】:

我有一个 XML,它的标签对应于三种类型的 Java 对象,这些对象将从 XML 创建。对象的形式为:

A
- static Map<String, A>
- String name
- String aInfo1
- String aInfo2

B
- static Map<String, B>
- String name
- String bInfo1
- String bInfo2

C
- A aObject
- B bObject

现在,在我的 XML 中,我为 A 对象和 B 对象定义了一个标签列表,然后我为 C 对象定义了标签,这些标签使用那里的名称字段引用 A 和 B 对象。 我有两个要求:

  1. 在 A 和 B 中填充静态映射,同时从 XML 中读取 A 和 B 对象。这些映射将分别包含 A.name 到 A 和 B.name 到 B 的映射。
  2. 通过从 XML 标记中读取 A.name 和 B.name 来填充 C 对象,然后使用 A 和 B 对象中定义的映射。

我已经阅读了一些 Java 框架,例如 JAXB,但是我无法想出一种方法来从我的 XML 创建这种类型的对象。是否有 Java 框架可以开箱即用或以最少的逻辑执行此操作?

编辑:

还有一个要求: 我需要定义形式的 D 和 E 对象

D
- Map<A, E>

我将定义 E 对象,类似于在 web.xml 中定义 servlet 的方式,即首先定义 E 类的名称和类,然后在其他地方使用 E 的名称。此外,传递参数以实例化 E 对象。标签看起来像:

<E>
    <name>queryProcessor</name>
    <class>com.mydomain.QueryProcessor</class>
</E>

现在这将在 D 中定义 Map 的内容时使用

<D>
    <map>
        <A>name_of_some_A_object</A>
        <E name="queryProcessor">
            <param1>name_of_some_B_object</param1>
            <param2>name_of_some_B_object</param2>
        </E>
        <A>name_of_some_A_object</A>
        <E name="queryProcessor">
            <param1>name_of_some_B_object</param1>
            <param2>name_of_some_B_object</param2>
        </E>
     </map>
 </D>

本质上,D 中的映射将通过实例化一个基类型 E 的类来填充,该类使用传递给它的参数和一个由其名称引用的 A 的对象。

【问题讨论】:

  • 那个 XML 有多大? (如果它小于大约 20MB,你可以使用比它更大的更简单的结构)
  • 不幸的是,“静态”不能很好地转换为 XML。
  • 它非常小,它将填充大约 10 到 20 个 A 和 B 对象,以及大约 20-25 个 C 对象。我猜不到 100k
  • 对于这样一个简单的结构,自己做会简单得多:使用 XPath 并填充对象。
  • 我同意,但这只是开始。随着我的 XML 的发展,还会出现许多其他复杂的情况。我希望找到一些可以在处理其余部分的同时在几个地方连接一些逻辑的东西。

标签: java xml spring jaxb jibx


【解决方案1】:
  • 使用 XSD 指定正确的 XML 格式
  • 生成 JAXB 类

(如果您熟悉 JAXB 注释并希望使用 Java 而不是 XSD 来控制接口,也可以反过来做)。

注意:静态地图很可能不是您想要使用的。如果您详细说明您要解决的问题,我们可能会为您指出一些替代方法

编辑:

您是在谈论 XML 的格式吗?或者为什么我需要 XML?我需要 XML 才能使我的应用程序在 Java 之外可配置。

看来您是在重新发明轮子。看看 Spring,看看它是否符合您的需求。如果不是,请解释原因。

【讨论】:

  • 静态 Map 需要使用其名称查找类型 A 的对象。这对于填充 C 和 D 等其他对象很有用。
  • 您可能需要某种单例,但在大多数情况下,静态地图迟早会给您带来问题。
  • 如何使用 JAXB 初始化类型 E 的类?
  • 如果您想读取 XML,请使用 Unmarshaller:docs.oracle.com/javase/6/docs/api/javax/xml/bind/…
  • 仅仅阅读 XML 不是我想要的。正如我在问题中提到的那样,我需要以非常具体的方式阅读 XML 并填充我的对象。 JAXB 有可能吗?
【解决方案2】:

根据您的描述,这可以使用 Spring 等通用框架来完成,方法是更改​​ XML 或生成一个 XSTL,该 XSTL 从您的 XML 创建一个 Spring XML 配置文件。

Spring Core documentation 可能足以让您入门。 XML的一个例子是

<bean id="beanOneId" class="the.bean.Class">
    <property name="someProperty" value="staticValue">
    <property name="someOtherProperty" ref="beanTwoId">
</bean>
<bean id="beanTwoId" class="the.otherbean.Class">
    <property name="someOtherProperty" ref="beanOneId">
    <property name="someOtherProperty" ref="beanThreeId">
</bean>

但是你所描述的不应该太难用反射。假设没有其他对象需要在构造函数中引用(而是作为 setX),我将从扫描 xml 开始,创建并存储所有对象及其名称,并记住“连接”列表,以便制作。创建所有对象后,执行连接列表中的所有连接。

【讨论】:

  • 如何通过 Spring 做到这一点?需要在我的 XML 中进行哪些更改。如果需要,我可以完全更改 XML 格式。
  • 如果您查看 Spring Core 有将 bean 连接在一起的示例,并且可以相互引用。我将在答案中添加一个示例。
  • 在spring定义中将A、B、C、D、E的每个实例定义为一个bean,并注入适当的值。您可以随意管理结构,甚至填充地图!
  • 这听起来很奇怪,我怎样才能将 A,B... 的每个实例都作为一个 bean。 AFAIK 拥有作为不同类实例的 bean 是件好事。另外,我如何确保每次访问 E 类型的新实例时都会创建它们。
  • 如果 A 或 B 在构造函数中不接受参数并且它们具有 get/set 方法,那么您就可以开始了。如果您在 xml 中的 bean 定义上设置属性 scope="prototype",那么您每次请求该 bean 时都会获得一个新实例。
【解决方案3】:

也许你想看看 XStream:http://x-stream.github.io/

它是一个很好的库,可以将对象编组和解组到 XML 和从 XML 中解组,并且什么都不做(与 Spring 不同)。就像http://x-stream.github.io/tutorial.html 中的示例一样,您可以从 XML 加载对象,如下所示:

Person newJoe = (Person)xstream.fromXML(xml);

为了让 XStream 理解您的 XML,您需要设置一些别名,例如描述的 http://x-stream.github.io/alias-tutorial.html

单靠 XStream 并不能完全解决你的问题,主要是因为这两个静态地图。但是,您可以让 XStream 从 XML 中加载 As 和 B 的列表,然后从列表中构建两个映射。

对于引用 A 和 B 的对象 C,您可以阅读以下有关对象引用的教程:http://x-stream.github.io/graphs.html。如果它不适合您的需要,您总是可以轻松地构建另一个类来使用 XStream 从 XML 中读取必要的信息,例如

public class CInfo {
    public String aName;
    public String bName
}

并使用 CInfo 构造 C 实例。鉴于您已经有了 A 和 B 的实例映射的名称,这将是微不足道的。

【讨论】:

  • 我找不到它如何映射到我的要求。如果您使用过它,请告诉我如何使用 XStream 来完成我在问题中提到的操作。
  • @Ashish XStream 能够根据您的类定义从 XML 文件创建一个或多个对象。如xstream.codehaus.org/tutorial.htmlxstream.codehaus.org/alias-tutorial.html 所示。但是,我认为它不会完全解决您的问题,主要是由于静态字段要求。我将修改我的答案以提供更多详细信息。
  • @Ashish 我不认为任何框架或库可以做任何事情。但是,XStream 似乎是更简单的选择(与 JAXB 或 Spring 相比,我有一些不好的经验)
猜你喜欢
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 2019-09-17
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多