2011-03-21 34 views
17

Tôi có một tài liệu XML lớn mà tôi muốn chuyển đổi sang một hạt Java. Nó có rất nhiều thẻ và thuộc tính, nhưng tôi chỉ quan tâm đến một số thẻ và thuộc tính. Unfurtounately, có vẻ như là XStream buộc bạn phải khai báo một thuộc tính trong bean đó cho mỗi và mọi thẻ có thể có trong XML đó. Có cách nào để giái quyết vấn đề này không?Làm cách nào để XStream bỏ qua các thẻ chưa được ánh xạ khi phân tích cú pháp XML?

Trả lời

15

Khởi tạo XStream như được hiển thị bên dưới để bỏ qua các trường không được xác định trong bean của bạn.

XStream xstream = new XStream() { 
    @Override 
    protected MapperWrapper wrapMapper(MapperWrapper next) { 
     return new MapperWrapper(next) { 
      @Override 
      public boolean shouldSerializeMember(Class definedIn, String fieldName) { 
       if (definedIn == Object.class) { 
        return false; 
       } 
       return super.shouldSerializeMember(definedIn, fieldName); 
      } 
     }; 
    } 
}; 
+2

Điều này không hiệu quả đối với tôi khi sử dụng chú thích @XStreamImplicit trên bộ sưu tập. Ý tưởng nào? –

+0

Sử dụng @ com.thoughtworks.xstream.annotations.XStreamOmitField – timomeinen

+0

XStreamOmitField không hoạt động đối với tôi! Không thoáng qua như được đề xuất trong tài liệu XStream. – endless

5

Tôi đã làm việc theo cách của tôi xung quanh vấn đề này hôm nay và những gì tôi đã phát hiện ra là sử dụng return this.realClass(fieldName) != null; không phải là (luôn luôn) là một giải pháp làm việc tuy nhiên trên thực tế có một cách cho xStream để bỏ qua unmapped thẻ VÀ làm việc với các bộ sưu tập tiềm ẩn cùng một lúc.

Tại sao realClass(fieldName) điều sẽ không làm việc

Trong thực tế lừa với việc sử dụng

try { 
    return this.realClass(fieldName) != null; 
} catch (Throwable t) { 
    return false; 
} 

công trình. Những gì nó làm là cố gắng để đoán loại theo tên thẻ, xem liệu nó đã thành công và nếu không - trả về false. Vì vậy, nó sẽ hoàn toàn bỏ qua các thẻ như

<someUnknownTag>someContent</someUnknownTag> 

NHƯNG nó sẽ làm việc chỉ lên đến thời điểm (!) khi bằng cách nào đó một số "không cần thiết" tag sẽ xảy ra để có một tên có ý nghĩa mà realClass(fieldName) sẽ thực sự có thể trả về một cái gì đó không bằng null và thẻ đó sẽ không phải là thành viên của bất kỳ ImplicitCollection nào của bạn. Trong trường hợp đó, biết rằng lớp cho một phần tử xml có thể được xác định và không có trường nào được ánh xạ trong người dùng gõ XStream sẽ quyết định rằng "có thể phần tử này là từ một số bộ sưu tập ngầm định". Và nó sẽ thất bại rất sớm nếu không có bộ sưu tập như vậy cũng không phải là một lĩnh vực trong lớp học của bạn. Trong trường hợp của tôi có vấn đề các mảnh của xml là như thế này:

<url>http://somewhere.com</url> 

và, tất nhiên, đã có không Url url; cũng không @XStreamImplicit List<Url> url vào lớp học của tôi. Kết quả của việc có như vậy một XML và sử dụng "realClass" điều như sau:

com.thoughtworks.xstream.converters.ConversionException: Element url of type java.net.URL is not defined as field in type org.sample.xstream.SomeBean 

Cách đúng

Cách đúng sẽ được trở về đồng bằng false từ shouldSerializeMember trong trường hợp khi definedIn == Object.class (không sử dụng realClass(fieldName) công cụ).

Nhưng chỉ sử dụng return false một mình là không đủ. Tôi hình thức này nó sẽ gây ra XStream để lại bộ sưu tập tiềm ẩn trống rỗng.

Bí quyết ở đây là đảm bảo sử dụng @XStreamImplicit(itemFieldName = "something") thay vì chỉ sử dụng @XStreamImplicit mà không có thông số ngay cả trong trường hợp tên thẻ và loại chung chung của bộ sưu tập có cùng tên.

Vì vậy, các mã bên phải sẽ giống như thế này:

xstream = new XStream() { 
     @Override 
     protected MapperWrapper wrapMapper(MapperWrapper next) { 
      return new MapperWrapper(next) { 
       @Override 
       public boolean shouldSerializeMember(Class definedIn, String fieldName) { 
        if (definedIn == Object.class) { 
         //This is not compatible with implicit collections where item name is not defined 
         return false; 
        } else { 
         return super.shouldSerializeMember(definedIn, fieldName); 
        } 
       } 
      }; 
     } 
    }; 
    xsteam.processAnnotations(SomeRootEntry.class); 

Và bạn cần phải chắc chắn rằng trong lớp học của bạn bộ sưu tập tiềm ẩn của bạn được đánh dấu như thế này:

@XStreamImplicit(itemFieldName = "something") 
private List <Something> somethingList; 

ý rằng itemFieldName là rõ ràng được chỉ định mặc dù tham số kiểu chung của Danh sách có cùng tên. Điều này là rất quan trọng.

Trong trường hợp này khi gặp phải <something> thẻ XStream thậm chí sẽ không truy cập vào số shouldSerializeMember của bạn với tên trường đó. Nó sẽ chỉ biết trước rằng phần tử là từ các bộ sưu tập ngầm định.

Khi nó sẽ, hãy truy cập vào phương pháp của bạn khi gặp phải <url>http://somewhere.com</url> một lần nữa. Nhưng ở đây chúng tôi an toàn vì chúng tôi chỉ trả lại false.

Làm việc cho tôi! Hãy thử một lần.

11

XStream 1.4.5 giúp bạn dễ dàng xử lý các thẻ không xác định. Sử dụng ignoreUnknownElements() cho các thẻ chưa được triển khai hoặc đã bị xóa và bạn đang xử lý xml cũ. Bạn cũng có thể chỉ định thẻ cụ thể nào bạn muốn bỏ qua.


8

Kể từ XStream khai marshaller 1.4.5 durring nó đủ để sử dụng ignoreEnknownElements() phương pháp:

XStreamMarshaller marshaller = new XStreamMarshaller(); 
marshaller.getXStream().ignoreUnknownElements(); 
... 

để bỏ qua các yếu tố không cần thiết.

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