我对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
,那么以下几个条件可能是正确的。
- 元素同时是
nillable="true"
和minOccurs="0"
。在这种情况下,映射字段/属性上的null
意味着什么?当属性为JAXBElement
时,null值表示该元素不存在,JAXBElement
包装null表示具有xsi:nil="true"
的XML元素。 - 有两个全局元素具有相同的命名复杂类型。由于在JAXB中,类对应于复杂类型,因此需要一种方法来捕获遇到的根元素。
- http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
- 有一个选择结构,其中
foo
或bar
元素可以出现,它们是相同的类型。这里需要JAXBElement
,因为仅仅遇到String
值不足以指示应该封送哪个元素。 - 在包含属性的文档中遇到具有
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>