【问题标题】:Java XML binding with nested generic tags带有嵌套通用标记的 Java XML 绑定
【发布时间】:2012-09-22 01:56:02
【问题描述】:

我需要一种有效的方法将 XML 转换为 Java 中的有意义的域对象。下面是我必须使用的 XML 的选择(某些值已被遮盖)。以下是我必须处理的基本限制:

  1. 没有可使用的架构。由于变量“嵌套”,自动生成的架构效果不佳。
  2. 任何给定的域对象都可以包含 0-* 域对象标签
  3. 任何给定的域对象都可以包含 0-* 值标签。
  4. 并非所有的嵌套都是一样的。在某些情况下,值的“键”包括隐式嵌套。例如,“config[0].cbs”表示配置对象的集合,每个对象都有不同的 .cbs 值
  5. 可能无法更改 XML 结构。
  6. “表示”属性表示类型。
  7. “nestedKey”属性表示类型内的变量名。
  8. 这些 XML 文件可能非常大。

我尝试过使用 JAXB,但由于标签的“通用性”,事情并没有奏效。也许我的 JAXB-fu 不够。当前的实现(我继承了这个)是 SAX,但它实际上不起作用。我看过 XStream,但它似乎对标签假设了一些语义结构。

我想要一种代码最少、最灵活、最可扩展的方法来生成有意义的域对象。如果可能的话,我想避免嵌套 HashMaps(这是当前解决方案的一部分,不起作用)。欢迎创意、hack-y 或聪明的想法以及直截了当的“duh”答案。

XML 片段:

<?xml version="1.0"?>
<domain-objects>
    <types language="C++">
        <type prefix="bool" language-representation="bool" />
        <type prefix="char" language-representation="char" />
        <type prefix="domain_object" language-representation="opti::DomainObject" />
        <type prefix="domain_object" language-representation="DomainObject" />
        <type prefix="double" language-representation="double" />
        <type prefix="float" language-representation="float" />
...
    </types>
    <domain-object key="(unique object id)" represents="PerfSuite">
        <domain-object key="(unique object id)" nestedKey="testCore" represents="PerfTestCore">
            <value key="suiteUuid" type="stl_string">(unique object id)</value>
            <value key="suiteName" type="stl_string">(some name)</value>
            <value key="suiteId" type="int">(some number)</value>
            <value key="suiteDeleted" type="bool">false</value>
        </domain-object>
        <domain-object key="(unique object id)" nestedKey="testResults" represents="PerfTestResults">
            <domain-object key="(unique object id)" nestedKey="services_0" represents="PerfServiceResult">
                <domain-object key="(unique object id)" nestedKey="stepResults_0" represents="PerfStepResult">
                    <value key="ir.max" type="int64">(some number)</value>
                    <value key="ftd.avg" type="float">(some number)</value>
                    <value key="ftd.max" type="float">(some number)</value>
...
                </domain-object>
                <value key="duration" type="uint">(some number)</value>
                <value key="flow" type="uint16">(some number)</value>
...
                        <value key="config[1].flrThreshold" type="float">(some number)</value>
                        <value key="config[1].fdvPercent" type="float">(some number)</value>
                        <value key="index" type="uint16">(some number)</value>
                        <value key="config[0].cbs" type="uint64">(some number)</value>
                        <value key="svlanVid" type="uint16">(some number)</value>
                        <value key="config[1].availThreshold" type="float">(some number)</value>
...

【问题讨论】:

    标签: java xml binding


    【解决方案1】:

    没有一种工具可以完全为您解决这个问题。

    JAXB 可能仍然是解析部分的正确答案。如果您希望将每个域对象转换为您的实际域对象,则必须自己完成最后一遍。

    JAXB 将无法解析出“float”以确定它需要查找类型表以找到浮点映射到浮点。在您的对象中查找“config[1].fdvPercent”也超出了它的能力范围。

    据我所知,您有一个可以用模式描述的相当一致的文档结构。用 XML 模式编写或注释类应该很简单。

    domain-objects = types+, domain-object+
    domain-object = domain-object*, value*
    

    从这里开始,您的工作就完成了。我怀疑你需要一些东西:

    • 按类型解析每个元素中的字符串,以便您可以获取每个元素的值
    • 从类型的字符串值到每个类型解析器的映射(看起来您可能需要一个额外的映射步骤才能从您使用的 C++?类型到 Java 类型)
    • 值键的解析器,以便您可以找到将值应用到的变量
    • 一些反射来实例化对象并在创建的对象中设置值

    我猜不出 nestedKey 或代表对您意味着什么。这些可能需要额外的步骤。

    【讨论】:

    • 为了确保我理解,您说我需要:1) 从 XML 转换为通用域对象,然后 2) 从通用转换为 有意义 域对象。对吗?
    • 这就是它的要点。如果您不认为通用的“值”对象有用,那么您需要进行一些自己的转换。没有任何工具可以完全满足您的需求。
    • 马丁,感谢您的回答。这几乎是我得出的结论,我希望有另一种/更好的方法。我意识到没有一个“工具”可以做到这一点,但我希望有一种更聪明的方法来解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 2023-04-11
    相关资源
    最近更新 更多