2012-11-16 18 views
6

Tôi đang cố gắng phân tích cú pháp một số XML với EclipseLink MOXy và nó không hoạt động trên đường với thuộc tính xsi. Nếu tôi loại bỏ điều này, nó phân tích tốt. Tuy nhiên, tôi đã có 100GiB XML để lội qua và thay đổi các tệp nguồn không phải là một tùy chọn.Cách đặt không gian tên nhận biết sai?

Được đề nghị rằng nếu tôi có thể đặt XmlParser.setNamespaceAware(false) thì nó sẽ hoạt động - nhưng tôi không biết cách cấu hình cái này, mà không phá vỡ ngay vào ruột của MOXy.

<record> 
<header> 
    <!-- citation-id: 14404534; type: journal_article; --> 
    <identifier>info:doi/10.1007/s10973-004-0435-2</identifier> 
    <datestamp>2009-04-28</datestamp> 
    <setSpec>J</setSpec> 
    <setSpec>J:1007</setSpec> 
    <setSpec>J:1007:2777</setSpec> 
</header> 
<metadata> 
    <crossref xmlns="http://www.crossref.org/xschema/1.0" 
     xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd"> 
     <journal> 
      <journal_metadata language="en"> 
[...] 

Trường hợp ngoại lệ khi tôi nhận được tiền tố xsi: là hiện nay là:

org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException 
- with linked exception: 
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.XMLMarshalException 
Exception Description: An error occurred unmarshalling the document 
Internal Exception: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[13,107] 
Message: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?crossref&xsi:schemaLocation&xsi] 
+0

Sự cố ban đầu bạn đang gặp phải là gì? –

+0

@BlaiseDoughan được cập nhật. Thực sự hy vọng bạn có thể giúp :) –

+0

Trong trường hợp sử dụng của bạn, bạn có thể thêm khai báo 'xmlns: xsi' cần thiết không? Chỉ cần kiểm tra trước khi chúng ta đi sâu vào các tùy chọn thay thế. –

Trả lời

8

Hiện nay không phải là một lựa chọn trong EclipseLink JAXB (MOXy) nói với nó để bỏ qua không gian tên. Nhưng có một cách tiếp cận bạn có thể sử dụng bằng cách tận dụng trình phân tích cú pháp của StAX.

Demo

Bạn có thể tạo một Stax XMLStreamReader vào đầu vào XML mà không phải là không gian tên biết và sau đó có MOXY unmarshal từ đó.

package forum13416681; 

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Foo.class); 

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false); 
     StreamSource source = new StreamSource("src/forum13416681/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(source); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Foo root = (Foo) unmarshaller.unmarshal(xsr); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

Java Model (Foo)

package forum13416681; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

    private String bar; 

    public String getBar() { 
     return bar; 
    } 

    public void setBar(String bar) { 
     this.bar = bar; 
    } 

} 

Input (input.xml)

Dưới đây là một phiên bản đơn giản của XML từ câu hỏi của bạn. Lưu ý rằng XML này không đúng không gian tên đủ điều kiện vì nó thiếu khai báo không gian tên cho tiền tố xsi.

<?xml version="1.0" encoding="UTF-8"?> 
<foo xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd"> 
    <bar>Hello World</bar> 
</foo> 

Output

Dưới đây là sản phẩm chạy mã demo.

<?xml version="1.0" encoding="UTF-8"?> 
<foo> 
    <bar>Hello World</bar> 
</foo> 
2

Thay vì vô hiệu hóa nhận thức không gian tên hoàn toàn, bạn có thể sử dụng một cơ chế Stax-thực hiện cụ thể để khai báo tiền tố xsi trước, sau đó phân tích với không gian tên được kích hoạt. Ví dụ, với Woodstox bạn có thể nói:

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 
import com.ctc.wstx.sr.BasicStreamReader; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance("com.example"); 

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource source = new StreamSource("input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(source); 
     ((BasicStreamReader)xsr).getInputElementStack().addNsBinding(
       "xsi", "http://www.w3.org/2001/XMLSchema-instance"); 

và sau đó tạo ra các unmarshaller và unmarshal các xsr như trong Blaise's answer. Trong khi điều này rõ ràng ràng buộc bạn với một triển khai StAX cụ thể, điều đó có nghĩa là bạn không phải sửa đổi các lớp mô hình JAXB hiện có nếu họ mong đợi phần tử <crossref> và các phần tử con của nó nằm trong không gian tên http://www.crossref.org/xschema/1.0.

Các vấn đề liên quan