Search code examples
javaxmlxstream

XStream: Keep parts of the XML as XML


I have the following XML:

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

I would like to convert this to an instance of class Patient like this:

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

Is it possible to use XStream to convert only part of the XML and keep the report field in XML format? How can it be done?


Solution

  • I solved it by creating an Convertor implementation, as explained here. My solution for the problem is as follows:

    Patient.java

    public class Patient {
        String name;
        Report report;
    }
    

    Report.java

    public class Report {
        public String report;
    }
    

    An implementation of a Convertor for 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; 
        } 
    }
    

    Example use of the convertor with 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>