2015-04-14 17 views
6

Tôi sử dụng Jaxb2 và Spring. Tôi đang cố gắng để unmarshal một số XML được gửi bởi 2 của khách hàng của tôi.Jaxb bỏ qua không gian tên trên unmarshalling

Cho đến nay, tôi chỉ phải xử lý một khách hàng mà gửi một số xml như thế này:

<foo xmlns="com.acme"> 
    <bar>[...]</bar> 
<foo> 

được ràng buộc với một POJO như thế này:

@XmlType(name = "", propOrder = {"bar"}) 
@XmlRootElement(name = "Foo") 
public class Foo { 

    @XmlElement(name = "Bar") 
    private String bar; 

    [...] 
} 

tôi phát hiện ra rằng trước nhà phát triển đã mã hóa không gian tên trong unmarshaller để làm cho nó hoạt động.

Bây giờ, khách hàng thứ hai gửi cùng một XML nhưng thay đổi không gian tên!

<foo xmlns="com.xyz"> 
    <bar>[...]</bar> 
<foo> 

Rõ ràng, unmarshaller không unmarshall vì nó hy vọng một số {com.acme}foo thay vì {com.xyz}foo. Thật không may, yêu cầu khách hàng thay đổi XML không phải là một lựa chọn.

gì tôi đã cố gắng:

1) Trong application-context.xml, tôi đã tìm kiếm cho một cấu hình mà sẽ cho phép tôi bỏ qua không gian tên nhưng không thể tìm thấy một:

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
    <property name="packagesToScan"> 
    <list> 
     <value>com.mycompany.mypkg</value> 
    </list> 
    </property> 
    <property name="marshallerProperties"> 
    <map> 
     <entry key="???"><value type="java.lang.Boolean">false</value></entry> 
    </map> 
    </property> 
</bean> 

có vẻ như các tùy chọn khả dụng duy nhất là các tùy chọn được liệt kê trong Javadoc của Jaxb2Marshaller:

/** 
* Set the JAXB {@code Marshaller} properties. These properties will be set on the 
* underlying JAXB {@code Marshaller}, and allow for features such as indentation. 
* @param properties the properties 
* @see javax.xml.bind.Marshaller#setProperty(String, Object) 
* @see javax.xml.bind.Marshaller#JAXB_ENCODING 
* @see javax.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT 
* @see javax.xml.bind.Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION 
* @see javax.xml.bind.Marshaller#JAXB_SCHEMA_LOCATION 
*/ 
public void setMarshallerProperties(Map<String, ?> properties) { 
    this.marshallerProperties = properties; 
} 

2) Tôi cũng đã cố gắng để cấu hình unmarshaller trong các mã:

try { 
    jc = JAXBContext.newInstance("com.mycompany.mypkg"); 

    Unmarshaller u = jc.createUnmarshaller(); 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    dbf.setNamespaceAware(false);//Tried this option. 

    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.parse(xmlFile.toFile()); 
    u.unmarshal(new DOMSource(doc)); 
    return (Foo)u.unmarshal(new StreamSource(xmlFile.toFile())); 
} catch (ParserConfigurationException | SAXException | IOException | JAXBException e) { 
    LOGGER.error("Erreur Unmarshalling CPL"); 
} 

3) hình thức khác nhau với một SAXParser:

try { 
    jc = JAXBContext.newInstance("com.mycompany.mypkg"); 
    Unmarshaller um = jc.createUnmarshaller(); 
    final SAXParserFactory sax = SAXParserFactory.newInstance(); 
    sax.setNamespaceAware(false); 
    final XMLReader reader = sax.newSAXParser().getXMLReader(); 
    final Source er = new SAXSource(reader, new InputSource(new FileReader(xmlFile.toFile()))); 
    return (Foo)um.unmarshal(er); 
}catch(...) {[...]} 

một này hoạt động! Nhưng vẫn còn, tôi muốn có thể autowire Unmarshaller mà không cần conf này xấu xí mọi lúc.

Trả lời

1

Nhận biết tên gọi là tính năng của trình đọc/trình tạo/trình phân tích cú pháp tài liệu chứ không phải trình soạn thảo. Các phần tử XML từ các không gian tên khác nhau đại diện cho các thực thể == đối tượng khác nhau, do đó các trình marshallers không thể bỏ qua chúng.

Bạn đã tắt đúng không gian tên trong trình đọc SAX và khi bạn nói nó hoạt động. Tôi không hiểu vấn đề của bạn với nó, marshaller của bạn vẫn có thể được tiêm, sự khác biệt là trong việc thu thập dữ liệu đầu vào. Thủ thuật tương tự với trình tạo tài liệu cũng sẽ hoạt động (tôi sẽ thử nghiệm nó sau này), tôi nghi ngờ rằng bạn vẫn đang sử dụng marshaller với không gian tên "hardcoded" nhưng tài liệu của bạn là không gian tên miễn phí.

Trong dự án của tôi, tôi sử dụng XSLT để giải quyết vấn đề tương tự. Thiết lập không gian tên không gian là giải pháp chắc chắn dễ dàng hơn. Nhưng, với XSLT tôi có thể chọn loại bỏ một số không gian tên và xml đầu vào của tôi không phải lúc nào cũng giống nhau (bỏ qua các không gian tên) và đôi khi tôi phải đổi tên một vài thành phần để XSLT mang lại cho tôi sự linh hoạt bổ sung này.

Để loại bỏ không gian tên bạn có thể sử dụng như XSLT mẫu:

<xsl:stylesheet version="1.0" xmlns:e="http://timet.dom.robust.ed" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<xsl:template match="/"> 
    <xsl:copy> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="text() | processing-instruction() | comment()"> 
    <xsl:copy /> 
</xsl:template> 
</xsl:stylesheet> 

Sau đó, trong Java trước khi unmarshalling tôi chuyển đổi dữ liệu đầu vào:

Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource); 
Source source = new DOMSource(xml); 
DOMResult result = new DOMResult(); 
transformer.transform(source, result); 
Các vấn đề liên quan