【问题标题】:JAXB bindings for common nested types常见嵌套类型的 JAXB 绑定
【发布时间】:2012-09-05 21:46:47
【问题描述】:

我必须从我无法控制的外部系统解组和处理 XML。 XML 是我认为的俄罗斯娃娃格式,处理起来并不容易。

XML 共享在通用 XSD 文件中声明的通用类型。但是,当 JABX 为这些类型生成 JAVA 类时,每个外部类都包含通用类型的嵌套声明,这使得它们就 JAVA 而言是不同的类型。

我希望有通用的 JAVA 函数来处理 XML 中的通用嵌套类型,但这不起作用,因为在 JAXB 类中这些通用类型是不相关的。

这使得我需要处理这些常见类型的 JAVA 代码非常混乱,我一直在尝试使用 JAXB 绑定来解决问题。但我一直没有成功。所以我的问题是: 鉴于这种 XML/XSD 格式,是否可以通过绑定或其他方法生成常见类型的 JAVA 代码?

举个例子;

XML CLASSA 和 CLASSB 中有两个类。两者都包含一个复杂类型,其类型为 testTYPE,它是一个字符串。 XSD 是:

CLASSA.XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:nstype="http://www.test.com/nstypes"
elementFormDefault="qualified">
<xs:import namespace="http://www.test.com/nstypes" schemaLocation="nstypes.xsd"/>
    <xs:element name="CLASSA">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Prop" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="PROP" minOccurs="0">
                                <xs:complexType>
                                    <xs:sequence>   
                                        <xs:element name="Value" type="nstype:testTYPE" minOccurs="0"/>
                                    </xs:sequence>  
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>  
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    </xs:schema>

B 类具有相同的结构,只是名称不同。

CLASSB.XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:nstype="http://www.test.com/nstypes"
elementFormDefault="qualified">
<xs:import namespace="http://www.test.com/nstypes" schemaLocation="nstypes.xsd"/>
    <xs:element name="CLASSB">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Prop" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="PROP" minOccurs="0">
                                <xs:complexType>
                                    <xs:sequence>   
                                        <xs:element name="Value" type="nstype:testTYPE" minOccurs="0"/>
                                    </xs:sequence>  
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>  
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    </xs:schema>

nstype:testTYPE 类型的唯一元素 Value 是在 nstypes.xsd 中声明的。它实际上是一个 BASETYPE,它是一个字符串。

nstypes.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:nstypes="http://www.test.com/nstypes"
targetNamespace="http://www.test.com/nstypes"
elementFormDefault="unqualified">
<xs:complexType name="BASETYPE">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute name="TYPE" fixed="BASETYPE"/>
            <xs:attribute name="derived" use="optional"/>
            <xs:attribute name="readonly" use="optional"/>
            <xs:attribute name="required" use="optional"/>
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>
<xs:complexType name="testTYPE">
    <xs:simpleContent>
        <xs:extension base="nstypes:BASETYPE"/>
    </xs:simpleContent>
</xs:complexType>
</xs:schema>

CLASSA 和 CLASSB 的 XML 相似

ClassA.xml

<?xml version="1.0" encoding="UTF-8"?>
<CLASSA>
    <Prop>
        <PROP>
            <Value>AAA</Value>
        </PROP>
    </Prop>     
</CLASSA>

ClassB.xml

<?xml version="1.0" encoding="UTF-8"?>
<CLASSB>
    <Prop>
        <PROP>
            <Value>BBB</Value>
        </PROP>
    </Prop>     
</CLASSB>

一旦生成了 JAXB 类,我想编写如下代码:

测试JAXB

import java.io.InputStream;

import org.generated.CLASSA.CLASSA;
import org.generated.CLASSA.TestTYPE;
import org.generated.CLASSB.CLASSB;

public class testJAXB
{
    // there is a util function     public static Object loadXML(String xmlFile, String fileName) throws Exception;

    public static void main(String[] args) throws Exception
    {
        // create a ClassA & a ClassB
        CLASSA anAClass = (CLASSA) loadXML("C:\\input\\ClassA.xml", "CLASSA");
        CLASSB anBClass = (CLASSB) loadXML("C:\\input\\ClassB.xml", "CLASSB");

        static void printClass(TestTYPE v)
        {
            // as CLASSA.TestTYPE is imported so v is a CLASSA.TestTYPE
            System.out.println(v.toString());
        }

        // this call will work as there is a printClass which takes a CLASSA.TestTYPE
        printClass(anAClass.getProp().getPROP().getValue());

        // this call will not compile  becase there is no printClass which takes a CLASSA.TestTYPE
        printClass(anBClass.getProp().getPROP().getValue());

        System.out.println("complete.");
    }
}   

我真正想做的是实现函数 printClass()。我想这将需要一个 org.generated.TestTYPE 并且所有 JAXB 类都将使用 org.generated.TestTYPEs ratehr 而不是 org.generated.CLASSA.TestTYPEs 生成。 我希望这可以通过一些绑定魔法来实现。如果有人能指出我正确的方向,将不胜感激。

我有 C++ 而不是 JAVA 背景,如果我的某些术语不正确,敬请见谅。

杰罗姆

这就是我想看到的,但我在 CLASSA 中看到的 xjc

public CLASSA.Prop getProp()

其中 CLASSA.Prop 是静态类,其中包含一个

protected CLASSA.Prop.PROP  

这是另一个包含一个静态类

 protected TestTYPE value;

而 TestTYPE 是一个

org.generated.CLASSA.TestTYPE   

CLASSB 中的 TestTYPE 是一个

org.generated.CLASSB.TestTYPE

由于两个 TestTYPE 嵌套在不同的类中,它们是不同的类型。

基本上,在运行 xjc 时,我得到两个包含 TestTYPE 类的文件:

CLASSA/TestTYPE.JAVA

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2012.09.07 at 07:45:23 AM BST 
//

package org.generated.CLASSA;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for testTYPE complex type.
* 
* <p>The following schema fragment specifies the expected content contained within this class.
* 
* <pre>
* &lt;complexType name="testTYPE">
*   &lt;simpleContent>
*     &lt;extension base="&lt;http://www.test.com/nstypes>BASETYPE">
*     &lt;/extension>
*   &lt;/simpleContent>
* &lt;/complexType>
* </pre>
* 
* 
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "testTYPE")
public class TestTYPE
    extends BASETYPE
{


}

and 

CLASSB/TestTYPE.JAVA

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2012.09.07 at 07:45:23 AM BST 
//

package org.generated.CLASSB;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for testTYPE complex type.
* 
* <p>The following schema fragment specifies the expected content contained within this class.
* 
* <pre>
* &lt;complexType name="testTYPE">
*   &lt;simpleContent>
*     &lt;extension base="&lt;http://www.test.com/nstypes>BASETYPE">
*     &lt;/extension>
*   &lt;/simpleContent>
* &lt;/complexType>
* </pre>
* 
* 
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "testTYPE")
public class TestTYPE
    extends BASETYPE
{


}   

【问题讨论】:

    标签: java data-binding jaxb xsd xjc


    【解决方案1】:

    我认为 JAXB 不会分解这样的代码。 IMO 更简单的解决方案是编写类 Prop 的代码并在绑定文件中定义 B.Prop 和 A.Prop 都依赖于同一个类。

    例如使用 classImpl 属性。 http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html#wp148576

    【讨论】:

    • 谢谢,我会尝试并报告!
    • 嗨,我看过这个,我认为这是正确的做法。但这可能行不通。问题是您只能更改隐藏的实现。 getter 和 setter 必须在 CLASSA 或 CLASSB 包中返回一些东西,所以它们仍然不是一个常见的 java 类(我认为)。我已经发布了关于这个问题的另一个问题here
    【解决方案2】:

    给定这种 XML/XSD 格式,常见类型的 JAVA 代码可以是 通过绑定或其他方法生成?

    使用JDK的xjc tool

    将所有文件放在一个目录中,然后执行:

    xjc *.xsd
    

    你会看到它生成了文件:

    parsing a schema...
    compiling a schema...
    generated\CLASSA.java
    generated\CLASSB.java
    generated\ObjectFactory.java
    com\test\nstypes\BASETYPE.java
    com\test\nstypes\ObjectFactory.java
    com\test\nstypes\TestTYPE.java
    com\test\nstypes\package-info.java
    

    您会看到在 CLASSA.java 中有一个方法调用 getProp(),它返回一个 CLASSA.Prop,您可以在该方法上执行另一个 getProp():

    在 CLASSA 你有:

    public CLASSA.Prop getProp()
    

    在 CLASSA.Prop 你有:

    public CLASSA.Prop.PROP getPROP()
    

    CLASSA.Prop.PROP 中的值是 com.test.nstypes.TestTYPE 类型,这是您的常用类型,不依赖于 CLASSA 或 CLASSB。

    【讨论】:

    • 这就是我想看到的,但我在 CLASSA 中看到的 xjc
    • 忽略那条评论,我会在回答中回复
    猜你喜欢
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    相关资源
    最近更新 更多