工作中涉及到XML数据输出,每年报表都会有局部指标的变化,相应的XML节点也会有相应的变更,同时还需能导出往年的数据。这样的要求,需要我们对数据库表的设计的时候采用行设计来。
数据表的设计:
当报表变化增加指标时,只需增加一行数据即可。
XML节点表设计:
输出XML每种报表都有有三个共同特点,,一是取数据,二是取节点,三是数据和节点的组合。代码设计如下
基类:
/**
* XML数据输出
* @author Administrator
*
* @param <T>
*/
public abstract class GenerateXML<T> {
/**
* 获取节点数据
* @param paramMap
* @return
*/
protected abstract List<T> getNodeData(Map<String,Object> paramMap);
/**
* 获取节点XML配置
* @param paramMap
* @return
*/
protected abstract List<NodeXMLInfo> getNodeXML(Map<String,Object> paramMap);
/**
* 组装节点
* @param root
* @param paramMap
* @return
*/
public abstract Element assemblyNode(Element root, Map<String,Object> paramMap, int signNode) throws Exception;
}
子类:业务类
/**
* 银行利润表XML
* @author Administrator
*
*/
public class BankProfitXML extends GenerateXML<BankProfitInfo> {
@Override
protected List<BankProfitInfo> getNodeData(Map<String,Object> paramMap) {
return null;
}
@Override
protected List<NodeXMLInfo> getNodeXML(Map<String,Object> paramMap) {
return null;
}
@Override
public Element assemblyNode(Element root, Map<String,Object> paramMap, int signNode) throws Exception{
List<BankProfitInfo> bpDatas = getNodeData(paramMap);
List<NodeXMLInfo> nxNodes = getNodeXML(paramMap);
Element changeNode = root;
for(NodeXMLInfo vNx : nxNodes){//节点
//生成节点路径
String[] nodeSplit = vNx.getXmlPathNode().split("/");
for (int i=0; i<nodeSplit.length; i++){
String nodeName = nodeSplit[i];
if (changeNode.getChild(nodeName) != null) {//节点存在
changeNode = (Element) changeNode.getContent((changeNode.getChildren().size())-1);
}else {//创建新节点
changeNode.addContent(new Element(nodeName));
}
}
//根据具体情况做处理
//生成末级节点--这里要 根据数据的类型进行相应的转换
String lastNodeName = vNx.getXmlLastNode(); //末级节点
String dataField = vNx.getDataField(); //对应数据字段属性
int rowOrder = vNx.getRowOrder();
Double nodeValue = 0.0;
for(BankProfitInfo vBp : bpDatas){//数据
if(vBp.getRowOrder().intValue()==rowOrder){
nodeValue = (Double)vBp.getClass().getField(dataField).get(vBp);
break;
}
}
changeNode.addContent(new Element(lastNodeName).addContent(nodeValue.toString()));
}
return changeNode;
}
}
如果存储数据内容采用了列式存储,组合代码变更如下:
List<BankProfitInfo> bpDatas = getNodeData(paramMap);
List<NodeXMLInfo> nxNodes = getNodeXML(paramMap);
Element changeNode = root;
Boolean repeatNode;
for(BankProfitInfo vBp : bpDatas){//数据
repeatNode = true;//指定重复节点
for(NodeXMLInfo vNx : nxNodes){//节点
//生成节点路径
String[] nodeSplit = vNx.getXmlPathNode().split("/");
for (int i=0; i<nodeSplit.length; i++){
String nodeName = nodeSplit[i];
if (changeNode.getChild(nodeName) != null) {//节点存在
if ((i==signNode)&&(repeatNode==true)){//指定继续生成节点
changeNode.addContent(new Element(nodeName));
changeNode = (Element) changeNode.getContent((changeNode.getChildren().size())-1);
}else{//获取节点的子节点
changeNode = (Element) changeNode.getContent((changeNode.getChildren().size())-1);
}
}else {//创建新节点
changeNode.addContent(new Element(nodeName));
}
if(i==signNode) repeatNode = false;
}
//生成末级节点--这里要 根据数据的类型进行相应的转换
String lastNodeName = vNx.getXmlLastNode(); //末级节点
String dataField = vNx.getDataField(); //对应数据字段属性
Double nodeValue = (Double)vBp.getClass().getField(dataField).get(vBp);
changeNode.addContent(new Element(lastNodeName).addContent(nodeValue.toString()));
}
}