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;
}