2011-08-31 24 views
5

Tôi có XML sau:XStream: Giữ các bộ phận của XML như XML

<patient> 
    <name>Mr. Sick</name> 
    <report> 
     <paragraph><bold>Conclusion</bold>text...</paragraph> 
    </report> 
</patient> 

Tôi muốn chuyển đổi này để một thể hiện của lớp bệnh nhân như thế này:

Class Patient { 
    String name = "Mr. Sick"; 
    String report = "<paragraph><bold>Conclusion</bold>text...</paragraph>"; 
} 

Có thể thế nào để sử dụng XStream để chỉ chuyển đổi một phần của XML và giữ trường báo cáo theo định dạng XML? Nó được hoàn thiện bằng cách nào?

+1

Bạn có thể làm điều này bằng cách sử dụng thực hiện JAXB (Metro, EclipseLink MOXY, Apache JaxMe), với chú thích '@ XmlAnyElement': http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html –

+0

Cảm ơn. Mặc dù tôi không sử dụng giải pháp này, nó giúp tìm ra câu trả lời. Tìm kiếm trên @XmlAnyElement kết hợp với XStream đã cho tôi đủ thông tin để giúp tôi tiếp tục. Tôi đã đăng câu trả lời cho câu hỏi này. – boes

Trả lời

4

Tôi giải quyết nó bằng cách tạo ra một thực hiện Convertor, như được giải thích here. Giải pháp của tôi cho vấn đề là như sau:

Patient.java

public class Patient { 
    String name; 
    Report report; 
} 

Report.java

public class Report { 
    public String report; 
} 

An thực hiện một Convertor cho XStream

public class ReportConverter implements Converter { 

    @Override 
    public boolean canConvert(Class classs) { 
     System.out.println("canConvert: " + classs.getName()); 
     return classs.equals(Report.class); 
    } 

    @Override 
    public void marshal(Object value, HierarchicalStreamWriter writer, 
      MarshallingContext context) { 
     // not used in this example 
    } 

    // goes recursive through all the nodes in <report> 
    String getNodeAsText(HierarchicalStreamReader reader) { 
     String result; 
     result = "<" + reader.getNodeName() + ">" + reader.getValue(); 
     while (reader.hasMoreChildren()) { 
      reader.moveDown(); 
      result += getNodeAsText(reader); 
      reader.moveUp(); 
      result += reader.getValue(); 
     } 
     result += "</" + reader.getNodeName() + ">"; 
     return result; 
    } 

    @Override 
    public Object unmarshal(HierarchicalStreamReader reader, 
      UnmarshallingContext context) { 
     Report xReport = new Report(); 
     xReport.report = reader.getValue(); 
     while (reader.hasMoreChildren()) { 
      reader.moveDown(); 
      xReport.report += getNodeAsText(reader); 
      reader.moveUp(); 
      xReport.report += reader.getValue(); 
     } 
     return xReport; 
    } 
} 

Ví dụ sử dụng công cụ chuyển đổi với XStream

XStream xStream = new XStream(); 
xStream.registerConverter(new ReportConverter()); 
xStream.alias("patient", Patient.class); 
xStream.alias("report", Report.class); 
String xml = "<patient><name>Mr. Sick</name><report><paragraph>" + 
     "some text here<bold>Conclusion</bold>text...</paragraph>" + 
     "<sdf>hello world</sdf></report></patient>"; 
Patient patient = (Patient)xStream.fromXML(xml); 
System.out.println("patient.name: " + patient.name); 
System.out.println("patient.report: " + patient.report.report); 

Output

patient: Mr. Sick 
patient.report: <paragraph>some text here<bold>Conclusion</bold>text... 
    ...</paragraph><sdf>hello world</sdf> 
3

Tôi không có câu trả lời cho câu hỏi nhưng tôi đề xuất một giải pháp thay thế có thể có thể hữu ích.

Có lẽ bạn nên thoát khỏi nội dung của trường report. Điều này sẽ giúp bạn tránh xml không hợp lệ có thể rất có vấn đề ở thời gian không cân bằng.

Dưới đây là một trong những cách đơn giản để làm điều đó (sử dụng commons libray từ apache org.apache.commons.lang.StringEscapeUtils):

class Patient { 
    String name = "Mr. Sick"; 
    String report = StringEscapeUtils.escapeHtml(
     "<paragraph><bold>Conclusion</bold>text...</paragraph>"); 

    // report = "&lt;paragraph&gt;&lt;bold&gt;Conclusion&lt;/bold&gt;text...&lt;/paragraph&gt;" 
} 
+0

Tôi cũng nghĩ rằng điều này sẽ làm việc. Ý kiến ​​hay! – carlspring

+0

Điều đó sẽ hoạt động nếu tôi bắt đầu với cá thể của lớp Bệnh nhân và sau đó tạo XML. Tôi cần nó theo cách khác. Tôi có một cơ sở dữ liệu đầy đủ với các thông điệp XML có vấn đề. Tôi muốn chuyển đổi chúng sang một lớp java như trong ví dụ của tôi. – boes

+0

Và bạn đã thử mọi thứ với XStream chưa? – Wivani

2

phiên bản tốt hơn của getNodeAsText() trong đó bao gồm các thuộc tính của mỗi nút:

private String getNodeAsText(HierarchicalStreamReader reader) {

StringBuilder str = new StringBuilder(); 
str.append("<") 
    .append(reader.getNodeName()); 

for (int i = 0; i < reader.getAttributeCount(); i++) { 
    String name = reader.getAttributeName(i); 
    String value = reader.getAttribute(i); 
    str.append(" ") 
    .append(name) 
    .append("=\"") 
    .append(value) 
    .append("\""); 
} 
str.append(">") 
    .append(reader.getValue()); 

while (reader.hasMoreChildren()) { 
    reader.moveDown(); 
    str.append(getNodeAsText(reader)); 
    reader.moveUp(); 
    str.append(reader.getValue()); 
} 
str.append("</") 
    .append(reader.getNodeName()) 
    .append(">"); 

return str.toString(); 

}

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