數據綁定系列最終篇:實現 Marshaller 將任意 JavaBean 風格物件轉為 XML 文檔。不依賴原始 Schema,透過反射遍歷 getter 產生屬性與巢狀元素,輸出獨立於 Schema 的純淨 XML,支援 OutputStream 靈活寫入。
public class Marshaller {
// 靜態入口
public static void marshall(Object obj, OutputStream out) throws IOException {
new Marshaller().writeXMLRepresentation(obj, out);
}
// 遞歸構建 JDOM Element
private Element getXMLRepresentation(Object obj) throws IOException {
Class> clazz = obj.getClass();
String name = BindingUtils.initialLowercase(clazz.getSimpleName().replace("Impl", ""));
Element element = new Element(name);
for (Method m : clazz.getMethods()) {
if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
try {
Object value = m.invoke(obj);
String prop = BindingUtils.initialLowercase(m.getName().substring(3));
if (value.getClass().getName().startsWith("java.lang.")) {
element.setAttribute(prop, value.toString()); // 原生型別 → 屬性
} else {
element.addContent(getXMLRepresentation(value)); // 複雜型別 → 子元素
}
} catch (Exception e) {
throw new IOException(e);
}
}
}
return element;
}
// 輸出
private void writeXMLRepresentation(Object obj, OutputStream out) throws IOException {
Document doc = new Document(getXMLRepresentation(obj));
new XMLOutputter(" ", true).output(doc, out); // 2 空格縮排
}
}
public class TestMapper {
public static void main(String[] args) throws Exception {
// 1. XML → Java
Object o = Unmarshaller.unmarshall(new File("xml/example.xml").toURL());
WebServiceConfiguration cfg = (WebServiceConfiguration) o;
// 2. Java → XML (輸出到標準輸出)
Marshaller.marshall(cfg, System.out);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<webServiceConfiguration name="Unsecured Web Listener" version="1.1">
<portType protocol="http" number="80" protectedPort="false"/>
<documentType index="*.html,*.xml" root="/usr/local/enhydra/html" error="error.html"/>
</webServiceConfiguration>
與原始 XML 僅差異於:無 Schema 引用、無命名空間宣告、屬性順序不同 — 語義完全等價。
public class WebService {
private File configFile;
private WebServiceConfiguration config;
public void start() throws IOException {
config = Unmarshaller.unmarshal(configFile.toURL());
}
public void stop() throws IOException {
Marshaller.marshal(config, new FileOutputStream(configFile));
}
}
啟動時解組,關閉時封存,業務邏輯零 XML 感知。
代碼已適配 JDOM Beta 5 API 變更,建議同步升級依賴。