2011-08-31 52 views
5

我有下面的XML:XStream的:保持XML的部分作爲XML

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

我想將其轉換爲像這類患者的實例:

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

是否有可能使用XStream只轉換部分XML並將報表字段保存爲XML格式?如何做呢?

+1

你可以使用JAXB實現(新城的EclipseLink莫西,阿帕奇這樣做JaxMe),與'@ XmlAnyElement'註釋:http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html –

+0

感謝。儘管我沒有使用這個解決方案,但它有助於找到答案。在XStream中搜索@XmlAnyElement,給了我足夠的信息讓我重新開始。我發佈了我對這個問題的回答。 – boes

回答

4

我解決它通過創建一個轉換器實現,如解釋here。我對問題的解決方案如下:

Patient.java

public class Patient { 
    String name; 
    Report report; 
} 

Report.java

public class Report { 
    public String report; 
} 

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

實施例使用的帶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); 

輸出

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

我沒有對提出的問題的答案,但我建議的替代方案,也許可以幫助。

你或許應該逃避report字段的內容。這將幫助您避免無效的xml,這在解組時可能非常成問題。

這裏有一個簡單的方法來做到這一點(使用公共來自Apache的org.apache.commons.lang.StringEscapeUtils 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;" 
} 
+0

我也認爲這會奏效。好主意! – carlspring

+0

如果我從Patient類實例開始,然後創建XML,那將起作用。我需要另一種方式。我有一個充滿有問題的XML消息的數據庫。我喜歡將它們轉換爲java類,如我的示例中所示。 – boes

+0

你有沒有用XStream自己嘗試過任何東西? – Wivani

2

getNodeAsText()的更好的版本,其中包括每個節點的屬性:

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

}