Dom4j操作word格式xml文件

1.word文件转xml之后源码文件分析

1.1word内容

其实所有的word内容都在图中的标识处,这里用idea做了收起,看49-7205行说明里面有7000多行

1.2命名空间

很重要,使用dom4j时,带冒号的标签,dom4j无法使用原生api直接进行操作,必须要有对应的命名空间

1.3 一般内容

样式和内容

1.4表格标签

<w:tbl>表示表格,可以理解为html中的<table>

<w:tr>表示行,<w:tc>表示列

2.需求

需要获取到表格位置,使用freemaker的list标签来循环表格数据

实现思路

1.获取到<w:tbl>标签

2.找到最后一行<w:tr>标签

3.在这一行的前后加上<#list listname as object> 和</#list>

3.技术选型

为什么要选择dom4j

目前有四种方案

1.DOM(JAXP Crimson解析器)

DOM以及广义的基于树的处理具有几个优点。首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像SAX那样是一次性的处理。DOM使用起来也要简单得多。

2.SAX

SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据

3.JDOM 

JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。

学习成本更低

4.DOM4J 

虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。xsd文档 (在电子招投标用过)

 

最终选择DOM4J

原因:

1)DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.

2)JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。

4.代码

引入依赖

                <dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.23</version>
		</dependency>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<dependency>
			<groupId>jaxen</groupId>
			<artifactId>jaxen</artifactId>
			<version>1.1.6</version>
		</dependency>

方法 操作表格

说明:为什么要加

document.getRootElement().addNamespace("w","http://schemas.openxmlformats.org/wordprocessingml/2006/main");

因为根节点没有w的命名空间,无法获取w:tabl的标签

最后要去掉,不然会影响word格式,打开显示为空

private void addListDocumentForTable(Document document) {
        document.getRootElement().addNamespace("w","http://schemas.openxmlformats.org/wordprocessingml/2006/main");
        List nodes =  document.getRootElement().selectNodes("//w:tbl");
        Iterator iter = nodes.iterator();
        while (iter.hasNext()) {
            tableIndex++;
            Element element = (Element) iter.next();
            Iterator iterator = element.elementIterator("tr");
            while (iterator.hasNext()) {
                Element nameElement = (Element) iterator.next();
                if(!iterator.hasNext()){
                    Element currentElement = nameElement;
                    Element pNode = nameElement.getParent();
                    pNode.remove(nameElement);
                    Element listElementHead = pNode.addElement("w:r");
                    listElementHead.setText("<#list "+listTableName.get(tableIndex-1)+" as "+listTableName.get(tableIndex-1)+" > ");
//                    listElementHead.setText("<#list listLeadergroup as listLeadergroup>");
                    pNode.add(currentElement);
                    Element listElementTail = pNode.addElement("w:r");
                    listElementTail.setText("</#list>");
                }
            }
        }
        document.getRootElement().remove(new Namespace("w","http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
    }

操作一般内容

    public void replaceDocumentBychr(Element element) {
        // 枚举根节点下所有子节点
        for (Iterator ie = element.elementIterator(); ie.hasNext();) {
            Element elementa = (Element) ie.next();
            // 枚举当前节点下所有子节点
            for (Iterator ieson = elementa.elementIterator(); ieson.hasNext();) {
                Element elementSon = (Element) ieson.next();
                if(elementSon.getText().contains("*")){
//                    System.out.println(elementSon.getName() + ":"+ elementSon.getText());
                    String textNew = replaceText(elementSon.getText());
                    elementSon.setText(textNew);
                }
            }
            replaceDocumentBychr(elementa);
        }
    }

    public String replaceText(String text){
        Integer cnt = getCountByChr(text,"**");
        Integer index = text.indexOf("**");
        i++;
        if(cnt>1){
            text = text.substring(0,index+2).replace("**","${"+listParamCode.get(i-1)+"}")+text.substring(index+2);
            return replaceText(text);
        }else{
            text = text.replace("**","${"+listParamCode.get(i-1)+"}");
        }

        return text;
    }

    private Integer getCountByChr(String text, String chr) {
        int count = 0;
        int index;
        //先查,赋值,判断
        while((index=text.indexOf(chr))!=-1){
            count++;
            text = text.substring(index + chr.length());
        }
        return count;

    }

PS:参考

Dom4j完整API(中文) https://www.cnblogs.com/sharpest/p/7877501.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值