XStream:将XML的一部分保留为XML

时间:2023-02-07 15:48:09

I have the following XML:

我有以下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?

是否可以使用XStream仅转换部分XML并将报告字段保留为XML格式?如何做呢?

3 个解决方案

#1


4  

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

我通过创建Convertor实现来解决它,如此处所述。我对这个问题的解决方案如下:

Patient.java

Patient.java

public class Patient {
    String name;
    Report report;
}

Report.java

Report.java

public class Report {
    public String report;
}

An implementation of a Convertor for XStream

用于XStream的Convertor的实现

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 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>

#2


3  

I don't have the answer for the question asked but I suggest an alternative that could maybe help.

我没有得到问题的答案,但我建议一个可能有帮助的替代方案。

You should probably escaping the content of the report field. This will help you avoid invalid xml which can be very problematic at unmarshal time.

您应该可以转义报告字段的内容。这将帮助您避免无效的xml,这在解组时非常有问题。

Here is one simple way to do that (using the commons libray from apache org.apache.commons.lang.StringEscapeUtils):

这是一种简单的方法(使用apache org.apache.commons.lang.StringEscapeUtils中的commons libray):

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;"
}

#3


2  

Better version of getNodeAsText() that includes the attributes of each node:

更好的getNodeAsText()版本,包含每个节点的属性:

private String getNodeAsText(HierarchicalStreamReader reader) {

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();

}

}

#1


4  

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

我通过创建Convertor实现来解决它,如此处所述。我对这个问题的解决方案如下:

Patient.java

Patient.java

public class Patient {
    String name;
    Report report;
}

Report.java

Report.java

public class Report {
    public String report;
}

An implementation of a Convertor for XStream

用于XStream的Convertor的实现

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 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>

#2


3  

I don't have the answer for the question asked but I suggest an alternative that could maybe help.

我没有得到问题的答案,但我建议一个可能有帮助的替代方案。

You should probably escaping the content of the report field. This will help you avoid invalid xml which can be very problematic at unmarshal time.

您应该可以转义报告字段的内容。这将帮助您避免无效的xml,这在解组时非常有问题。

Here is one simple way to do that (using the commons libray from apache org.apache.commons.lang.StringEscapeUtils):

这是一种简单的方法(使用apache org.apache.commons.lang.StringEscapeUtils中的commons libray):

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;"
}

#3


2  

Better version of getNodeAsText() that includes the attributes of each node:

更好的getNodeAsText()版本,包含每个节点的属性:

private String getNodeAsText(HierarchicalStreamReader reader) {

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();

}

}