需求:
报文(数据集)中含有多个字段,要解析为多个含有意义的字段。
设计:
1、将报文格式定义在xml中
2、通过格式xml来解析数据
当前体会到此设计的优势:
1、报文格式可在xml中配置。报文格式调整不涉及程序调整。
2、程序可读性强。
实现:
一、自定义xml文件
1、节点标签
2、子节点标签
3、数据标签
4、描述标签
5、起始下标
6、长度标签
example.xml:
<?xml version="1.0" encoding="UTF-8"?>
<infos>
<!-- 数据截取模板定义 -->
<info>
<dataName>data1</dataName>
<desc>数据1</desc>
<startIndex>6</startIndex>
<length>10</length>
</info>
<infos>
二、读取XML文件解析
1、读取xml,获取Document。
public static Document getDocument(Class<?> cls, String fileName) throws Exception{
InputStream in = null;
try{
//把要解析的XML文档转化为输入流,方便DOM解析器解析
in = cls.getClassLoader().getResourceAsStream(fileName);
//得到DOM解析器的工厂实例
//从DOM工厂获得DOM解析器
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return builder.parse(in);
}finally{
if(in != null){
in.close();
}
}
return null;
}
补充:
(1)导入包org.w3c.dom.Document
a. dom,为文档对象模型 (DOM) 提供接口,该模型是 Java API for XML Processing 的组件 API。
具体详见:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/org/w3c/dom/package-summary.html。
b. Document 接口表示整个HTML、XML。
具体详见:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/org/w3c/dom/Document.html。
另:
a. javax.swing.text 提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类。类相关说明详见:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/javax/swing/text/package-use.html#javax.swing.text
b. javax.swing.text.Document 作为swing文本组建模型的文本容器。
(2)得到XML文档的根节点
Element rootNode = document.getDocumentElement();
(3)从根节点获取子节点
NodeList nodes = rootNode.getChildNodes();
(4)DOM Document Object Model,也即文档对象模型。
对xml文件进阶操作,用Java W3C DOM 进行XML操作的例子,可详见:
http://blog.csdn.net/cds27/article/details/2139110。
(5)从xml设置到Map
注意:应在类中静态块中,进行初始化。
static{
setSubTemplateToMap();
}
private static final String SUBTEMPLATEFILENAME = "example.xml";
private static Map subTemplateMap = new HashMap<String, List<Map<String,String>>>();
public static void setSubTemplateToMap(){
try {
Document document = XmlDocumentUtils.getDocument(SUBTEMPLATEFILENAME );
NodeList nodeList = document.getElementsByTagName("info");
List<Map<String,String>> list = new ArrayList<Map<String,String>>();
for ( int i = 0; i < nodeList.getLength(); i++){
Map<String,String> result = new HashMap<String, String>();
String dataName = document.getElementsByTagName("dataName").item(i).getFirstChild().getNodeValue();
String startIndex = document.getElementsByTagName("startIndex").item(i).getFirstChild().getNodeValue();
String length = document.getElementsByTagName("length").item(i).getFirstChild().getNodeValue();
if(StringUtils.empty(dataName)){
throw new Exception("第["+i+"]个"+"dataName"+"标签的内容不能为空");
}
if ( StringUtils.empty(startIndex)){
throw new Exception("第["+i+"]个"+"startIndex"+"标签的内容不能为空");
}
if ( StringUtils.empty(length)){
throw new Exception("第["+i+"]个"+"length"+"标签的内容不能为空");
}
result.put("dataName", dataName);
result.put("startIndex", startIndex);
result.put("length", length);
list.add(result);
}
subTemplateMap.put(SUBTEMPLATEFILENAME.substring(0,SUBTEMPLATEFILENAME.lastIndexOf(".")), list);
} catch ( Throwable e ) {
e.printStackTrace();
}
}
/*解析数据*/
public static boolean getStrByTemplateMap(String data,String templateName,Map<String,String> result){
boolean bool = false;
List<Map<String,String>> list = subTemplateMap.get(templateName);//获取数据匹配模板
if(list != null && list.size()>0){
for(Map<String,String> map : list){
try{
String dataName = map.get("dataName");
int startIndex = Integer.parseInt(map.get("startIndex"));
int length = Integer.parseInt(map.get("length"));
String subData = data.substring(startIndex,startIndex+length).trim();
result.put(dataName, subData);
}catch(Throwable e){
//logger.error("通过模板解析数据异常",e);
if(!bool){
bool = true;
}
}
}
}
return bool;
}
补充:
a. NodeList getElementsByTagName(String tagName) Document成员方法
按文档顺序返回包含在文档中且具有给定标记名称的所有 Element 的 NodeList。
b. int getLength() NodeList类成员方法 获取NodeList的长度,即Node数目。
c. Node item(int index) NodeList类成员方法 返回集合中第index个项。
NodeList详见:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/org/w3c/dom/NodeList.html。
d. Node getFirstChild() 此节点的第一个子节点。
e. String getNodeValue()此节点的值。
注意:
a. xml文件要能读取到,可放置在同一目录下。
b. 若无日志操作的,可注释掉logger部分。
c. 引用的工具类StringUtils,可将其替换为 字符串判NULL或判空字符串。