引包
<dependency>
<groupId>org.codehaus.castor</groupId>
<artifactId>com.springsource.org.exolab.castor.xml</artifactId>
<version>1.2.0</version>
</dependency>
目标 XML文件
target.xml
<?xml version="1.0" encoding="UTF-8"?>
<plugin name="测试Castor解析" version="1.1">
<extension element-class="demo.zh.castor.dto.Extension" id="extension">
<operation name="java对象1">
<desc>java对象1的描述</desc>
<index>1</index>
</operation>
<operation name="java对象2">
<desc>java对象2的描述</desc>
<index>10</index>
</operation>
</extension>
</plugin>
配置Mapping需要的配置信息
config.xml
config.xml 的作用是:Mapping对象根据config.xml里的映射关系,将target.xml里解析出来的数据,通过反射注入对我们所需的对象。
案列所示,有三个层级关系,分别使用对象Plugin、Extension、Operation来表示
<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<description> the Config of the Castor Mapping </description>
<class name="demo.zh.castor.dto.Plugin" identity="id">
<map-to xml="plugin"/>
<field name="id">
<bind-xml name="id" node="attribute"/>
</field>
<field name="name">
<bind-xml name="name" node="attribute"/>
</field>
<field name="version">
<bind-xml name="version" node="attribute"/>
</field>
<field name="extensions"
type="demo.zh.castor.dto.Extension"
collection="collection">
<bind-xml name="extension"/>
</field>
</class>
<class name="demo.zh.castor.dto.Extension"
identity="id" auto-complete="true">
<map-to xml="extension"/>
<field name="id">
<bind-xml name="id" node="attribute"/>
</field>
<field name="className">
<bind-xml name="element-class" node="attribute"/>
</field>
<field name="operationGroup"
type="demo.zh.castor.dto.Operation"
collection="collection">
<bind-xml auto-naming="deriveByClass"/>
</field>
</class>
<class name="demo.zh.castor.dto.Operation" identity="name"
auto-complete="true">
<map-to xml="operation"/>
<field name="name">
<bind-xml name="name" node="attribute"/>
</field>
<field name="desc">
<bind-xml name="desc" node="element"/>
</field>
<field name="index" type="integer">
<bind-xml name="index" node="element"/>
</field>
</class>
</mapping>
所需对象
Plugin
@Getter
@Setter
public class Plugin implements Serializable {
private Long id;
private String name;
private String version;
private ArrayList<Extension> extensions;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Plugin{");
sb.append("name='").append(name).append('\'');
sb.append(", version='").append(version).append('\'');
sb.append(", extensions=").append(extensions);
sb.append('}');
return sb.toString();
}
}
Extension
@Getter
@Setter
public class Extension {
private String id;
private String className;
private ArrayList<Operation> operationGroup;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Extension{");
sb.append("id='").append(id).append('\'');
sb.append(", className='").append(className).append('\'');
sb.append(", operationGroup=").append(operationGroup);
sb.append('}');
return sb.toString();
}
}
Operation
@Getter
@Setter
public class Operation implements Serializable {
private String name;
private String desc;
private Integer index;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Operation{");
sb.append("name='").append(name).append('\'');
sb.append(", desc='").append(desc).append('\'');
sb.append(", index=").append(index);
sb.append('}');
return sb.toString();
}
}
XMLHelper
解析xml的方法定义在这里
@Slf4j
@Component
public class XMLHelper {
/**
* 加载Mapping的配置信息
*
* @param mappingPath mapping 文件的地址
* @return Mapping
*/
private Mapping loadMapping(String mappingPath) throws CustomException {
Mapping result;
if (StringUtil.isEmpty(mappingPath)) {
throw new CustomException("mappingPath is Empty...");
}
result = new Mapping();
String absolutePath = FileUtil.getFileAbsolutePath(mappingPath, "Mapping配置文件");
try {
result.loadMapping(absolutePath);
} catch (IOException e) {
log.error("文件不存在");
} catch (MappingException e) {
log.error("加载Mapping所需配置信息失败,(可能原因:xml文件中的配置项与java类不合)原因:" + e.getMessage(), e);
throw new CustomException("加载Mapping所需配置信息失败");
}
return result;
}
/**
* 解析xml文件
*
* @param xmlPath xml文件在工程里的相对路径
* @param mappingConfigPath 解析xml文件,储存Mapping对象需要的配置信息的辛苦xml文件的相对练路径
* @return Plugin对象
* @throws CustomException 系统自定义异常
*/
public Plugin parse(String xmlPath, String mappingConfigPath) throws CustomException {
if (StringUtil.isEmpty(xmlPath) || StringUtil.isEmpty(mappingConfigPath)) {
log.error(String.format("解析XML文件时,发现文件地址为空。" +
"xmlPath = [%s] , mappingConfigPath = [%s]", xmlPath, mappingConfigPath));
throw new CustomException("文件地址为空");
}
Mapping mapping = this.loadMapping(mappingConfigPath);
String xmlAbsolutePath = FileUtil.getFileAbsolutePath(xmlPath, "被解析的XML文件");
String encoding = getDeclaredFileEncoding(xmlAbsolutePath);
Unmarshaller unmarshaller = new Unmarshaller();
try {
unmarshaller.setMapping(mapping);
return parseByUnmarshaller(unmarshaller, xmlAbsolutePath, encoding);
} catch (Exception e) {
log.error("使用Unmarshaller解析XML失败,原因:" + e.getMessage(), e);
// 解决xml汉字乱码引起的xml解析失败的问题,用UTF-8重新解析一次
return parseByUnmarshaller(unmarshaller, xmlAbsolutePath, CharSetEnum.UTF8.value);
}
}
private Plugin parseByUnmarshaller(Unmarshaller unmarshaller, String xmlAbsolutePath, String encoding) throws CustomException {
Plugin result;
File target = new File(xmlAbsolutePath);
try (InputStream input = new FileInputStream(target);
Reader reader = new InputStreamReader(input, encoding)) {
result = (Plugin) unmarshaller.unmarshal(reader);
} catch (Exception e) {
log.error(String.format("解析xml[%s]失败,原因:%s", xmlAbsolutePath, e.getMessage()), e);
throw new CustomException("解析xml失败");
}
return result;
}
/**
* 获取xml文件的编码
*
* @param filePath 文件地址
* @return charSet eg:UTF-8
*/
private String getDeclaredFileEncoding(String filePath) {
String encoding = CharSetEnum.GBK.value;
if (!filePath.endsWith(".xml")) {
return encoding;
}
try (FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line = bufferedReader.readLine();
// 简单判断,<?xml version="1.0" encoding="UTF-8" ?> 必须写在首行,且不换行
if (line.startsWith("<?xml") && line.endsWith("?>") && line.toUpperCase().contains(CharSetEnum.UTF8.value)) {
encoding = CharSetEnum.UTF8.value;
}
} catch (IOException e) {
log.error("获取文件编码失败,原因:" + e.getMessage(), e);
}
return encoding;
}
}
调用XMLHelper的parse方法
@Slf4j
public class LoadXML {
public static void main(String[] args) throws CustomException {
XMLHelper xmlHelper = new XMLHelper();
String xmlPath = "castor/xml/target.xml";
String mappingConfigPath = "castor/mapping/config.xml";
Plugin result = xmlHelper.parse(xmlPath, mappingConfigPath);
log.info(result.toString());
}
}
输出结果
...LoadXML - Plugin{name='测试Castor解析', version='1.1', extensions=[Extension{id='extension', className='demo.zh.castor.dto.Extension', operationGroup=[Operation{name='java对象1', desc='java对象1的描述', index=1}, Operation{name='java对象2', desc='java对象2的描述', index=10}]}]}
网友评论