數據綁定系列第三篇:實現 Unmarshaller 將符合 Schema 的 XML 實例文檔轉換為生成類的 Java 物件。採用 JDOM 解析、反射調用 setter、資料類型映射、遞歸處理巢狀元素,附完整測試與 Web Service 啟動範例。
<?xml version="1.0"?>
<webServiceConfiguration xmlns="https://www.enhydra.org"
version="1.1" name="Unsecured Web Listener">
<port number="80" protocol="http" protectedPort="false"/>
<document root="/usr/local/enhydra/html" index="*.html,*.xml" error="error.html"/>
</webServiceConfiguration>
SAXBuilder 解析 XML 為 JDOM DocumentWebServiceConfigurationImpl)setXxxsetXxxpublic static Object unmarshall(URL instanceURL) throws IOException {
Document doc = new SAXBuilder().build(instanceURL);
return new Unmarshaller().getJavaRepresentation(doc.getRootElement());
}
// DataMapping.getParameter(String value, Class targetType)
public static Object getParameter(String value, Class> type) {
String t = type.getName();
if (t.equals("java.lang.String")) return value;
if (t.equals("int") || t.equals("java.lang.Integer")) return Integer.valueOf(value);
if (t.equals("long") || t.equals("java.lang.Long")) return Long.valueOf(value);
if (t.equals("float") || t.equals("java.lang.Float")) return Float.valueOf(value);
if (t.equals("double") || t.equals("java.lang.Double")) return Double.valueOf(value);
if (t.equals("boolean") || t.equals("java.lang.Boolean")) return Boolean.valueOf(value);
return null; // 可擴充 Date 等
}
for (Element child : rootElement.getChildren()) {
String setter = "set" + BindingUtils.initialCaps(child.getName());
Method method = findMethod(objectClass, setter);
Object childObj = getJavaRepresentation(child); // 遞歸
method.invoke(obj, childObj);
}
Object o = Unmarshaller.unmarshall(new File("xml/example.xml").toURL());
WebServiceConfiguration cfg = (WebServiceConfiguration) o;
assertEquals("Unsecured Web Listener", cfg.getName());
assertEquals(80, cfg.getPort().getNumber());
assertEquals("http", cfg.getPort().getProtocol());
for (URL url : configUrls) {
WebServiceConfiguration cfg = Unmarshaller.unmarshal(url);
WebService svc = new WebService();
svc.setName(cfg.getName());
svc.setPortNumber(cfg.getPort().getNumber());
svc.setProtocol(cfg.getPort().getProtocol());
svc.start();
}
代碼已適配 JDOM Beta 5,方法名稱有變更,請使用隨文提供的最新源碼包。