如何让 Moxy/JAXB 解组以接受 XML 文档中的前缀 [重新定位为让 JAXB 接受根节点元素中缺少的命名空间 xmlns]

问题描述

我正在尝试从 Web 服务解组 XML 文档,但无法设置 JAXB/Moxy 以读取命名空间前缀“ae”。

我可以通过从 XML 文档中手动去除前缀来使其部分工作。我也尝试过使用 package-info.java 方法。

请帮忙指出我哪里出错了?

XML 文档示例

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:diag="urn:SerenaDiagnostics" xmlns:ae="urn:sbmappservices72">
    <SOAP-ENV:Header>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
    <ae:GetItemsByQueryResponse>
    <ae:return>
<ae:item>
<ae:id>
<ae:displayName>
</ae:displayName>
<ae:id>15</ae:id>
<ae:uuid>36df5681-652b-4fb9-b7e4-b14935c6920b</ae:uuid>
<ae:tableId>1064</ae:tableId>
<ae:tableIdItemId>1064:15</ae:tableIdItemId>
<ae:issueId>
</ae:issueId>
</ae:id>
<ae:title>CONFIGURATION</ae:title>
<ae:url>http://scsmwdcuapp01:80/tmtrack/tmtrack.dll?IssuePage&amp;RecordId=15&amp;Template=view&amp;TableId=1064</ae:url>
<ae:extendedField>
<ae:id>
<ae:displayName>Related Category</ae:displayName>
<ae:id>827</ae:id>
<ae:uuid>043aa994-e155-449c-bf8c-2397e5d4c975</ae:uuid>
<ae:dbName>RELATED_CATEGORY</ae:dbName>
</ae:id>
<ae:value>
<ae:displayValue>MAINFRAME APPLICATION</ae:displayValue>
<ae:internalValue>1063:3</ae:internalValue>
<ae:uuid>b2814974-c370-409a-980a-d8b9af9de7b7</ae:uuid>
</ae:value>
</ae:extendedField>
<ae:extendedField>
<ae:id>
<ae:displayName>SNSys_ID</ae:displayName>
<ae:id>828</ae:id>
<ae:uuid>4baeb994-a23d-4ccf-bf93-786047c09bb9</ae:uuid>
<ae:dbName>SNSYS_ID</ae:dbName>
</ae:id>
<ae:value>
<ae:displayValue>122f66b26fe57500bd06cbe64f3ee456</ae:displayValue>
<ae:internalValue>122f66b26fe57500bd06cbe64f3ee456</ae:internalValue>
<ae:uuid>
</ae:uuid>
</ae:value>
</ae:extendedField>
<ae:subtasks>
</ae:subtasks>
</ae:item>
<ae:item>
.....

Moxy XML 绑定文件。

<?xml version="1.0"?>
<xml-bindings 
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="egress"
        version="2.5"
        xml-mapping-metadata-complete="true">   
    <xml-schema element-form-default="QUALIFIED">
        <xml-ns prefix="ae" namespace-uri="urn:sbmappservices72"/>
    </xml-schema>
    <java-types>
        <java-type name="QueryResponse" xml-accessor-type="FIELD">
        <xml-root-element name="ae:GetItemsByQueryResponse"/>
            <java-attributes>
                <xml-element java-attribute="returnRecords" xml-path="return"/>
            </java-attributes>
        </java-type>
        <java-type name="AuxRecords" xml-accessor-type="FIELD">
        <xml-root-element name="return"/>
            <java-attributes>
                <xml-element java-attribute="recordsList" xml-path="item"/>
            </java-attributes>
        </java-type>
        <java-type name="AuxRecord" xml-accessor-type="FIELD">
        <xml-root-element name="result"/>
            <java-attributes>
                <xml-element java-attribute="name" xml-path="title/text()"/>
                <xml-element java-attribute="id" xml-path="id"/>
                <xml-element java-attribute="extensionList" xml-path="extendedField"/>
            </java-attributes>      
        </java-type>
        <java-type name="AuxRecordId" xml-accessor-type="FIELD">
        <xml-root-element name="id"/>
            <java-attributes>
                <xml-element java-attribute="itemId" xml-path="id/text()"/>
                <xml-element java-attribute="tableId" xml-path="tableId/text()"/>
            </java-attributes>      
        </java-type>
        <java-type name="ExtendedField" xml-accessor-type="FIELD">
        <xml-root-element name="extendedField"/>
            <java-attributes>
                <xml-element java-attribute="id" xml-path="id"/>
                <xml-element java-attribute="value" xml-path="value"/>
            </java-attributes>      
        </java-type>
        <java-type name="FieldId" xml-accessor-type="FIELD">
        <xml-root-element name="id"/>
            <java-attributes>
                <xml-element java-attribute="displayName" xml-path="displayName/text()"/>
            </java-attributes>      
        </java-type>
        <java-type name="FieldValue" xml-accessor-type="FIELD">
        <xml-root-element name="value"/>
            <java-attributes>
                <xml-element java-attribute="displayValue" xml-path="displayValue/text()"/>
            </java-attributes>      
        </java-type>
    </java-types>
</xml-bindings>

部分 Java 类列表

@XmlRootElement(name="ae:GetItemsByQueryResponse")
@XmlAccessorType(XmlAccessType.FIELD)
public class QueryResponse {
    
    @XmlElement (name="return")
    AuxRecords returnRecords = null;

    public AuxRecords getReturnRecords() {
        return returnRecords;
    }

    public void setReturnRecords(AuxRecords records) {
        this.returnRecords = records;
    }
}

@XmlRootElement(name="return")
@XmlAccessorType(XmlAccessType.FIELD)
public class AuxRecords {

    @XmlElement(name="item")
    private List<AuxRecord> recordsList = null;

    public List<AuxRecord> getRecords() {
        return recordsList;
    }
    
    public void setRecords(List<AuxRecord> inputRecordsList) {
        this.recordsList = inputRecordsList;
    }   
}

@XmlRootElement(name="item")
@XmlAccessorType(XmlAccessType.FIELD)
public class AuxRecord {

    // snow=u_category,sbm=ae:title
    @XmlElement (name="title")
    String name = null;
    
    // sbm=ae:id
    @XmlElement (name="id")
    AuxRecordId id = null;

    @XmlElement(name="extendedField")
    private List<ExtendedField> extensionList = null;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public AuxRecordId getId() {
        return id;
    }
    
    public void setId(AuxRecordId inputId) {
        this.id = inputId;
    }

    public List<ExtendedField> getExtensionList() {
        return extensionList;
    }

    public void setExtensionList(List<ExtendedField> extensionList) {
        this.extensionList = extensionList;
    }

    public Object getExtensionSnSysId() {
        // TODO Auto-generated method stub
        return null;
    }
}

@XmlRootElement(name="extendedField")
@XmlAccessorType(XmlAccessType.FIELD)
public class ExtendedField {
    
    @XmlElement (name="id")
    FieldId id;
    
    @XmlElement (name="value")
    FieldValue value;
    
    public FieldId getId() {
        return id;
    }
    public void setId(FieldId id) {
        this.id = id;
    }
    public FieldValue getValue() {
        return value;
    }
    public void setValue(FieldValue value) {
        this.value = value;
    }
}

我在 POJO 类中解组 XML 文档的代码。

public class Test {

    public static void main(String[] args) throws JAXBException{
        
        Map<String,Object> properties = new HashMap<String,Object>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE,"xml-bindings.xml");
        JAXBContext context1 = JAXBContext.newInstance(new Class[] {QueryResponse.class},properties);
        
        Marshaller marshal1 = context1.createMarshaller();
        Unmarshaller umarshal1 = context1.createUnmarshaller();
//      umarshal1.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());      
        QueryResponse qresp = (QueryResponse) umarshal1.unmarshal(new File("c:\\temp\\ae_egress.xml"));
        
        marshal1.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
        marshal1.marshal(qresp,System.out);

    }
}

例外

Exception Description: An error occurred unmarshalling the document
Internal Exception: org.xml.sax.SAXParseException; systemId: file:/c:/temp/ae_egress.xml; lineNumber: 1; columnNumber: 35; The prefix "ae" for element "ae:GetItemsByQueryResponse" is not bound.]
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:980)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:126)
    at com.citi.sbm.egress.Test.main(Test.java:27)

更新

将输入源 XML 文档根元素节点更改为

<ae:GetItemsByQueryResponse xmlns:ae="urn:sbmappservices72">
<ae:return>
.....

清除异常。由于它被假定为 SOAP 响应,因此我无法像在测试 ae_egress.xml 中那样修改它。除了在将 DOM 文档或 InputStream 或 XmlInputStream 传递给 unmarshal 之前动态修改它之外,JAXB 或 MOXy 中是否有一些开关或选项也可以解决问题?

这是位于测试包中的 package-info.java 文件。

@XmlSchema (  namespace="urn:sbm,appservices72",elementFormDefault=XmlNsForm.QUALIFIED,xmlns={
@XmlNs(prefix="ae",namespaceURI="urn:sbmappservices72")}
)
package egress;
import javax.xml./bind.annotation.*;

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)