从WDSL生成的JAXB POJO似乎使用起来很麻烦。



我对SOAP和将WSDL转换为POJO并不陌生。我已经成功连接到web服务并检索我需要的数据。

问题在于遍历WSDL创建的对象层次结构。在生成的类中存储的大多数变量都是JAXBElement<NameOfJavaClassHere>类型的。所以当我想要那个对象时,我需要发出一个调用,比如ListOfEntitiesType loe = ents.getListOfEntities().getValue();, .getValue()是我的问题所在。

是否存在一种方法使它成为一个更平滑的集成?如果我必须继续做一个getValue(),那将是一个1000刀的死亡。

感觉他们在客户层面留下了一个他们不需要的间接层次。

我试过用JAXBContent对象来解组xml,网上有很多关于如何做到这一点的例子,但在这种情况下它不起作用。我的对象返回null

WSDL不应该用泛型生成不需要所有这些转换的POJO吗?

我是否在java 1.7附带的wsimport命令上使用了错误的设置?

我应该使用一个不同的类似于导入的程序来生成POJO吗?

如果我必须坚持.getValue()的东西,我想我宁愿做一个xpath接口到原始XML或把整个东西变成哈希表和数组列表,而不是处理这个。

至少那样的话,我就可以直接获得我想要的信息

这个XML模式可能是在某些官僚规则的影响下开发的。考虑,例如

<xs:element minOccurs="0" name="DUNSNumber" nillable="true" type="xs:string"/>

产生一个字段

protected JAXBElement<String> dunsNumber;

导致您(正确地)抱怨的高度间接的get和set过程。- XML Schema条目是什么意思?它表示元素是字符串,可以省略,并且必须能够区分空字符串和不存在的字符串,即使元素存在

这里有一个小实验:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
       version="1.0">
<xs:element name="root" type="RootType"/>
<xs:complexType name="RootType">
  <xs:sequence>
    <xs:element maxOccurs="unbounded" name="elem"  type="ElemType"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="ElemType">
  <xs:sequence>
    <xs:element minOccurs="0" name="str01"    type="xs:string"/>
    <xs:element minOccurs="1" name="str1"     type="xs:string"/>
    <!-- The following element compiles to a JAXBElement<String> -->
    <xs:element minOccurs="0" name="str01nil" nillable="true" type="xs:string"/>
    <xs:element minOccurs="1" name="str1nil"  nillable="true" type="xs:string"/>
  </xs:sequence>
</xs:complexType>
</xs:schema>

下面是一个XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <elem>
    <str01></str01>
    <str1></str1>
    <str01nil></str01nil>
    <str1nil></str1nil>
  </elem>
  <elem>
    <str1>must be there</str1>
    <str01nil xsi:nil="true"></str01nil>
    <str1nil>must be there</str1nil>
  </elem>
</root>

这是反编组例程打印的内容:

str01    []
str1     []
str01Nil []
str1Nil  []
str01    [null]
str1     [must be there]
str01Nil [null]
str1Nil  [must be there]

如果完全省略<str01nil xsi:nil="true"></str01nil>会发生什么?结果将是相同的,方法JAXBElement.getValue()将返回null,就是这样。

现在(很抱歉回答的长度),我们可以讨论您可以做些什么来返回从XML模式生成的"正常"Java代码。我只需删除nillable="true"并使用生成的代码。如果您封送,字段中的null将不会产生元素。在反编组时,您很有可能看到带有xsi:nil="true"的空元素。(保留minOccurs="0"是必要的。)

在一些用例中,JAXBElement需要能够往返XML Schema中定义的XML。如果你在生成的模型中看到大量的JAXBElement,那么以下几个条件可能是正确的。

  1. 元素同时是nillable="true"minOccurs="0"。在这种情况下,映射字段/属性上的null意味着什么?当属性为JAXBElement时,null值表示该元素不存在,JAXBElement包装null表示具有xsi:nil="true"的XML元素。
  2. 有两个全局元素具有相同的命名复杂类型。由于在JAXB中,类对应于复杂类型,因此需要一种方法来捕获遇到的根元素。
    • http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
  3. 有一个选择结构,其中foobar元素可以出现,它们是相同的类型。这里需要JAXBElement,因为仅仅遇到String值不足以指示应该封送哪个元素。
  4. 在包含属性的文档中遇到具有xsi:nil的元素。在本例中,仍然可以对该元素对应的对象进行反编组以保存属性值,但是JAXBElement仍然可以指示该元素为空。

减少模型中JAXBElement数量的机制

  • generateElementProperty设置为false的绑定文件

    <?xml version="1.0" encoding="UTF-8"?>
    <bindings xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
        version="2.1">
        <globalBindings>
            <generateElementProperty>false</generateElementProperty>
        </globalBindings>
    </bindings>
    
  • 简单的XJC插件- https://jaxb.java.net/2.1.2/docs/vendorCustomizations.html#simple

    <?xml version="1.0" encoding="UTF-8"?>
    <bindings xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
        xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
        xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
        version="2.1">
        <globalBindings>
            <xjc:simple />
        </globalBindings>
    </bindings>
    

相关内容

最新更新