JAX-WS/JAXB:无法通过bindings.xml定位WSDL中嵌入的XSD节点
问题
使用Maven插件com.sun.xml.ws:jaxws-maven-plugin从包含嵌入XSD的WSDL生成Java类,禁止修改WSDL或其Schema。目标是通过外部jaxb-bindings.xml给生成的ImportStatusReadRequest和ImportStatusReadResponse类添加@XmlRootElement注解,但XPath无法正确定位节点,执行jaxws:wsimport时报错:
[ERROR] XPath evaluation of "<node>" results in an empty target node
尝试过的方案:
- 全局使用
<xjc:simple />可以生成@XmlRootElement,但会自动复数化List属性(如List<ITEM>被命名为items而非item),不符合需求。
需求:
- 用XPath仅定位嵌入Schema中的特定类型
- 添加
@XmlRootElement注解且不启用List属性复数化
提供的配置文件:
pom.xml
<plugin> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>4.0.3</version> <configuration> <sourceDestDir>${project.basedir}/target/generated-sources</sourceDestDir> <destDir>${project.basedir}/target/generated-sources</destDir> <wsdlDirectory>${project.basedir}/src/main/resources/wsdl</wsdlDirectory> <bindingDirectory>${project.basedir}/src/main/resources/wsdl</bindingDirectory> </configuration> <executions> <execution> <id>default</id> <goals> <goal>wsimport</goal> </goals> </execution> </executions> </plugin>
SST-073.wsdl(简化版)
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions name="os_ImportStatusRead" targetNamespace="urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS" xmlns:p1="urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <wsdl:documentation/> <wsp:UsingPolicy wsdl:required="true"/> <wsp:Policy wsu:Id="OP_os_ImportStatusRead"/> <wsdl:types> <xsd:schema targetNamespace="urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS" xmlns="urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS" xmlns:p5="urn:be.ch:KTBE_ERP_FI:GENERAL" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:import namespace="urn:be.ch:KTBE_ERP_FI:GENERAL"/> <xsd:element name="ImportStatusRead_Response" type="ImportStatusRead_Response"/> <xsd:element name="ImportStatusRead_Request" type="ImportStatusRead_Request"/> <xsd:complexType name="ImportStatusRead_Response"> <!-- complexType definition --> </xsd:complexType> <xsd:complexType name="ImportStatusRead_Request"> <!-- complexType definition --> </xsd:complexType> </xsd:schema> <xsd:schema targetNamespace="urn:be.ch:KTBE_ERP_FI:GENERAL" xmlns="urn:be.ch:KTBE_ERP_FI:GENERAL" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="SenderParms"> <!-- complexType definition --> </xsd:complexType> <xsd:complexType name="ReturnCodeID"> <!-- complexType definition --> </xsd:complexType> </xsd:schema> </wsdl:types> <!-- wsdl:message and wsdl:service --> </wsdl:definitions>
当前jaxb-bindings.xml
<jaxws:bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:jaxws="https://jakarta.ee/xml/ns/jaxws" xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" version="3.0"> <jaxws:bindings wsdlLocation="SST-073.wsdl" node="wsdl:definitions/wsdl:types"> <!-- This adds @XmlRootElement annotation, but enable pluralisation --> <jaxws:bindings node="xs:schema"> <jaxb:globalBindings> <xjc:simple/> </jaxb:globalBindings> </jaxws:bindings> <!-- This fails to target the node --> <jaxws:bindings node="/xs:schema[@targetNamespace='urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS']"> </jaxws:bindings> </jaxws:bindings> </jaxws:bindings>
解决方案
核心问题修正
之前的XPath错误在于使用了绝对路径(/开头),而当前上下文是wsdl:types节点,应该使用相对路径匹配子节点。同时,我们需要仅针对目标类型启用<xjc:simple/>,避免全局复数化。
修改后的jaxb-bindings.xml
<jaxws:bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:jaxws="https://jakarta.ee/xml/ns/jaxws" xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" version="3.0"> <!-- 绑定到WSDL的types节点 --> <jaxws:bindings wsdlLocation="SST-073.wsdl" node="wsdl:definitions/wsdl:types"> <!-- 定位到目标命名空间的Schema --> <jaxws:bindings node="xs:schema[@targetNamespace='urn:be.ch:KTBE_ERP_FI:IMPORT_STATUS']"> <!-- 给ImportStatusRead_Request类型添加@XmlRootElement --> <jaxb:bindings node="xs:complexType[@name='ImportStatusRead_Request']"> <xjc:simple/> </jaxb:bindings> <!-- 给ImportStatusRead_Response类型添加@XmlRootElement --> <jaxb:bindings node="xs:complexType[@name='ImportStatusRead_Response']"> <xjc:simple/> </jaxb:bindings> </jaxws:bindings> </jaxws:bindings> </jaxws:bindings>
说明
- XPath修正:去掉了路径开头的
/,直接在当前wsdl:types上下文匹配目标Schema,避免空节点错误。 - 局部启用xjc:simple/:仅针对
ImportStatusRead_Request和ImportStatusRead_Response两个complexType启用<xjc:simple/>,确保只有这两个生成的类带有@XmlRootElement注解。 - 避免复数化:全局未启用
<xjc:simple/>,因此List属性会保持原始命名(如List<ITEM>仍命名为item)。
验证
执行mvn jaxws:wsimport后,检查生成的ImportStatusReadRequest.java和ImportStatusReadResponse.java,会发现已添加@XmlRootElement注解,同时其他List属性命名未被复数化。
内容的提问来源于stack exchange,提问作者Quad
相关产品推荐
相关产品推荐

