xml解析Excel导出

*若价格不公道,可以让提问者在平台追加赏金哦,平台是您利益的保证

已完成
xml解析Excel导出-176****6040
176****6040 3年前发布
悬赏:50.0 元

问题详情:分类: Java

解析xml文件excel导出,在线等大佬

*若价格不公道,可以让提问者在平台追加赏金哦,平台是您利益的保证。你觉得当前的价格如何呢,奉上您珍贵的一票吧

虚高0人次 适中0人次 偏低0人次

分享海报会更快解决你的问题哦!分享海报

参考答案:

七月coder 3年前解决
已赚445.0元

1. 问题背景:解析XML文本,并按照层级关系写入Excel。
xml文件结构:

其中menu_node标签下还有嵌套的menu_node标签,还有page标签;
page标签下有,perm标签。

生成的Excel文件样式:

不同层级的使用不同的缩进展示;
相同层级的属性,放在同一行,且使用空单元格隔开。

要求:解析的时候,实体类的属性上不要使用注解。

2. 解决方案分析

2.1 如何解析xml
使用Dom4j框架+递归来实现xml解析。
使用Dom4j,可以获取文档的根标签,每一个标签对象,从而获取标签的名称,使用`getAttribute()`获取到标签的某个属性的值;
使用`getChildren()`函数获取某个标签下的所有子标签。

2.2 如何操作Excel以及如何实现Excel的缩进和xml中的层级对应
使用Apache的POI框架,可以实现对Excel单元格的写入,样式设置等操作;
解析xml得到实体类,实体类中除了有存储必要的信息字段外,还需要有一个level字段,来表示当前结点的层级;如下图所示:

然后在写入Excel的时候,根据这个level字段,进行相关的缩进设置。如下图所示:


3. 具体实现和关键代码解析
3.1 导入相关依赖

包结构图

主要由两个方法完成:
    public static void main(String[] args) throws Exception {
//解析XML
List<MenuNode> list = parseXML();

//写入Excell
sinkToExcel(list);
}
3.2 解析XML
    private static List<MenuNode> parseXML() throws Exception {
SAXBuilder saxBuilder = new SAXBuilder();
InputStream is = new FileInputStream(new File("F:\\javaDev\\xml解析\\sys.txt"));
Document document = saxBuilder.build(is);
Element rootElement = document.getRootElement();
List<Element> children = rootElement.getChildren();
int level = 0;
List<MenuNode> list = null;
if (children != null && !children.isEmpty()) {
for (Element child : children) {
if (Objects.isNull(child)) continue;
String childName = child.getName();

//目前知道root下只有menu_node,仅处理menu_node
if (!"menu_node".equals(childName)) continue;
Attribute name = child.getAttribute("name");
if (Objects.isNull(name)) continue;
String nameValue = name.getValue();
MenuNode menuNode = new MenuNode();
menuNode.setLevel(level);
menuNode.setName(nameValue);

//解析MenuNode结点
parseMenuNode(menuNode, child.getChildren(), level + 1);
if (Objects.isNull(list)) list = new ArrayList<>();
list.add(menuNode);
}
}
return list;
}
parseMenuNode实现:
    private static MenuNode parseMenuNode(MenuNode menuNode, List<Element> children, int level) {
if (children != null && !children.isEmpty()) {
List<Page> pages = null;
List<MenuNode> list = null;
for (Element child : children) {
if (Objects.isNull(child)) continue;
String name = child.getName();
if (Objects.isNull(name)) continue;

//遇到相同结点
if ("menu_node".equals(name)) {
Attribute nameAttr = child.getAttribute("name");
if (Objects.isNull(nameAttr)) continue;
String value = nameAttr.getValue();
MenuNode menuNodeChild = new MenuNode();
menuNodeChild.setName(value);
menuNodeChild.setLevel(level);

//递归解析MenuNode 层级加一
parseMenuNode(menuNodeChild, child.getChildren(), level + 1);
if (Objects.isNull(list)) list = new ArrayList<>();
list.add(menuNodeChild);
} else if ("page".equals(name)) {
Attribute srcAttr = child.getAttribute("src");
if (Objects.isNull(srcAttr)) continue;
String srcValue = srcAttr.getValue();
Page page = new Page();
page.setSrc(srcValue);
page.setLevel(level);

//解析page结点
parsePage(page, child.getChildren(), level + 1);
if (Objects.isNull(pages)) pages = new ArrayList<>();
pages.add(page);
} else {
continue;
}
}
menuNode.setMenuNodes(list);
menuNode.setPages(pages);
}
return menuNode;
}
解析XML的输出得到一个List<MenuNode> 列表,里面已经把结点的属性和层级信息封装好。
3.3 写入Excel
写入Excel分为构造单元格和把输出流写到本地文件的过程;
    private static void sinkToExcel(List<MenuNode> list) throws IOException {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFCellStyle style = workbook.createCellStyle();

//设置单元格样式为普通文本
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("@"));
HSSFSheet sheet = workbook.createSheet("sheet1");
if(list!=null&&!list.isEmpty()){
for (MenuNode menuNode : list) {

//遍历结点树,构造单元格
transversalMenuNode(menuNode,sheet,style);
}
}

//写入文件
workbook.write(new FileOutputStream("E:\\My Documents\\Desktop\\result.xls"));
}
构造单元格:
    private static void transversalMenuNode(MenuNode menuNode, HSSFSheet sheet,HSSFCellStyle style){
HSSFCell cell = getCell(sheet,menuNode.getLevel(), style);
fillTextToCell(cell,menuNode.getName());
List<MenuNode> menuNodes = menuNode.getMenuNodes();
List<Page> pages = menuNode.getPages();
if(menuNodes!=null&&!menuNodes.isEmpty()){
for (MenuNode node : menuNodes) {

//递归构建
transversalMenuNode(node,sheet,style);
}
}
if(pages!=null&&!pages.isEmpty()){
for (Page page : pages) {

//传入level,当作缩进
HSSFCell cell1 = getCell(sheet, page.getLevel(), style);

fillTextToCell(cell1,page.getSrc());
List<Perm> perms = page.getPerms();
if(perms!=null&&!perms.isEmpty()){
for (Perm perm : perms) {
HSSFRow row = sheet.createRow(curLineNumber);
HSSFCell permNameCell = row.createCell(perm.getLevel());
HSSFCell permDescCell = row.createCell(perm.getLevel()+2);
permNameCell.setCellStyle(style);
permDescCell.setCellStyle(style);
curLineNumber++;
fillTextToCell(permNameCell,perm.getName());
fillTextToCell(permDescCell,perm.getDesc());
}
}
}
}
}
其中构建单元格的具体方法是getCell方法,
    private static HSSFCell getCell(HSSFSheet sheet,int columnNumber,HSSFCellStyle style){

//创建行
HSSFRow row = sheet.createRow(curLineNumber);

//根据传来的缩进参数,设置列
HSSFCell cell = row.createCell(columnNumber);
cell.setCellStyle(style);

//行下移
curLineNumber++;
return cell;
}
4. 总结
解决这个问题需要了解XML的解析方法,以及递归的使用。处理Dom4j,xml解析还有SAX,JDom等方式。


此处可发布评论

评论(1

七月coder 能力:50

2020-12-09 22:49:23

已请求加好友,请通过一下
点击加载更多
客服QQ 1913284695