Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用POI在给定段落前插入sdt?_Java_Apache Poi_Tableofcontents_Xwpf - Fatal编程技术网

Java 如何使用POI在给定段落前插入sdt?

Java 如何使用POI在给定段落前插入sdt?,java,apache-poi,tableofcontents,xwpf,Java,Apache Poi,Tableofcontents,Xwpf,我想在现有word文件的主体之前生成一个TOC。 我重新定义了一个自定义的XWPFDocument.createTOC函数,以生成一个风格符合我需要的TOC。 但在createTOC函数中,“this.getDocument().getBody().addNewSdt()”只能在body的最后一个位置插入sdt。我花了很多时间寻找一种方法来改变sdt元素的位置。 我发现这种方法最终可以奏效 Node body_node = doc.getDocument().getDomNode().item(

我想在现有word文件的主体之前生成一个TOC。 我重新定义了一个自定义的XWPFDocument.createTOC函数,以生成一个风格符合我需要的TOC。 但在createTOC函数中,“this.getDocument().getBody().addNewSdt()”只能在body的最后一个位置插入sdt。我花了很多时间寻找一种方法来改变sdt元素的位置。 我发现这种方法最终可以奏效

Node body_node = doc.getDocument().getDomNode().item(0);
NodeList nodeList = body_node.getChildNodes();
Node sdt_xxx = nodeList.item(8);
body_node.removeChild(sdt_xxx);
body_node.insertBefore(sdt_xxx ,nodeList.item(0));
此方法可以修改sdt的位置。但是此方法适用于CT类,因此在修改CT类后,XWPFDocument中的变量(如List、List)不会更改。我不知道如何修改XWPFDocument中的bodyelements,它是一个不可修改的变量。修改CT变量后,我不知道如何重新加载XWPFDocument对象

(将修改后的对象写入新文件后重新打开文件时,XWPFDocument对象可以更新。但我不想这样做,这个方法似乎太愚蠢了。)

那么,谁知道如何使用POI将sdt(TOC)添加到给定位置?
非常感谢。

您说您已经用自己的
createTOC
方法扩展了
XWPFDocument
。因此,您还可以提供一个
createTOC(org.apache.xmlbeans.XmlCursor)
以及
insertnewparagration(org.apache.xmlbeans.XmlCursor)
。在那里,光标确定TOC插入的位置

由于更新了bodyelements列表,扩展的
XWPFDocument
可以提供
重新创建BodyElementList
方法。然后,此方法在调用时重新创建所有必需的bodyelements列表

完整的示例来说明原理:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField;

import org.apache.xmlbeans.XmlCursor;

public class CreateWordTOC {
    
 static String cTStyleTOC1 =
  "<w:style xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:type=\"paragraph\" w:styleId=\"TOC1\">"
+ "<w:name w:val=\"toc 1\"/>"
+ "<w:basedOn w:val=\"Normal\"/>"
+ "<w:next w:val=\"Normal\"/>"
+ "<w:autoRedefine/><w:unhideWhenUsed/>"
+ "<w:rPr><w:b/><w:bCs/><w:caps/><w:color w:val=\"C00000\"/><w:sz w:val=\"32\"/><w:szCs w:val=\"32\"/></w:rPr>"
+ "</w:style>";

 static String cTStyleTOC2 =
  "<w:style xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:type=\"paragraph\" w:styleId=\"TOC2\">"
+ "<w:name w:val=\"toc 2\"/>"
+ "<w:basedOn w:val=\"Normal\"/>"
+ "<w:next w:val=\"Normal\"/>"
+ "<w:autoRedefine/><w:unhideWhenUsed/>"
+ "<w:rPr><w:i/><w:iCs/><w:sz w:val=\"28\"/><w:szCs w:val=\"28\"/></w:rPr>"
+ "</w:style>";

 public static void main(String[] args) throws Exception {

  //XWPFDocument document = new XWPFDocument(new FileInputStream("./WordDocument.docx"));
  MyXWPFDocument document = new MyXWPFDocument(new FileInputStream("./WordDocument.docx"));

  XWPFStyles styles = document.createStyles(); 
  CTStyles cTStyles = CTStyles.Factory.parse(cTStyleTOC1);
  CTStyle cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  cTStyles = CTStyles.Factory.parse(cTStyleTOC2);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  
  System.out.println(document.getBodyElements().size());
  System.out.println(document.getContentControls().size());
 
  //TOC before first parahraph
  XWPFParagraph paragraph = document.getParagraphs().get(0);
  XmlCursor cursor = paragraph.getCTP().newCursor();
  //document.createTOC(cursor, "Heading");
  document.createTOC(cursor, "berschrift"); // German style Ids are "berschrift1", "berschrift2", ... (from "Überschrift" umlaut is not used in Id)
  cursor.dispose();
  //TOC as last element in body
  //document.createTOC(null, "Heading");
  document.createTOC(null, "berschrift");
  
  System.out.println(document.getBodyElements().size());
  System.out.println(document.getContentControls().size());
  if (document.getContentControls().size() > 0 )
   System.out.println(document.getContentControls().get(0).getContent());


  FileOutputStream out = new FileOutputStream("./WordDocumentNew.docx");   
  document.write(out);
  out.close();
  document.close();

 }

}
import java.io.FileOutputStream;
导入java.io.FileInputStream;
导入org.apache.poi.xwpf.usermodel.*;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField;
导入org.apache.xmlbeans.XmlCursor;
公共类CreateWordTOC{
静态字符串cTStyleTOC1=
""
+ ""
+ ""
+ ""
+ ""
+ ""
+ "";
静态字符串cTStyleTOC2=
""
+ ""
+ ""
+ ""
+ ""
+ ""
+ "";
公共静态void main(字符串[]args)引发异常{
//XWPFDocument document=newxwpfdocument(newfileinputstream(“./WordDocument.docx”);
MyXWPFDocument document=新的MyXWPFDocument(新文件输入流(“./WordDocument.docx”);
XWPFStyles styles=document.createStyles();
CTStyles=CTStyles.Factory.parse(cTStyleTOC1);
CTStyle CTStyle=cTStyles.getStyleArray(0);
styles.addStyle(新的XWPFStyle(cTStyle));
cTStyles=cTStyles.Factory.parse(cTStyleTOC2);
cTStyle=cTStyles.getStyleArray(0);
styles.addStyle(新的XWPFStyle(cTStyle));
System.out.println(document.getBodyElements().size());
System.out.println(document.getContentControls().size());
//第一次帕拉赫之前的TOC
XWPFParagraph paragraph paragraph=document.getParagraphs().get(0);
XmlCursor cursor=段落.getCTP().newCursor();
//文件.createTOC(光标,“标题”);
document.createTOC(游标,“berschrift”);//德语样式的Id是“berschrift1”、“berschrift2”、…(来自“Überschrift”的umlaut未在Id中使用)
cursor.dispose();
//TOC作为主体中的最后一个元素
//document.createTOC(空,“标题”);
createTOC(空,“berschrift”);
System.out.println(document.getBodyElements().size());
System.out.println(document.getContentControls().size());
if(document.getContentControls().size()>0)
System.out.println(document.getContentControls().get(0.getContent());
FileOutputStream out=新的FileOutputStream(“./WordDocumentNew.docx”);
文件。写(出);
out.close();
document.close();
}
}
MyXWPFDocument.java:

import java.io.*; 
import java.math.BigInteger;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xwpf.usermodel.*; 
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class MyXWPFDocument extends XWPFDocument {
    
 private static final POILogger LOG = POILogFactory.getLogger(XWPFDocument.class);
    
 public MyXWPFDocument(InputStream is) throws IOException {
  super(is);   
 }
    
 public void createTOC(XmlCursor cursor, String headingStyleIdPrefix) {
  CTSdtBlock block = null;
  if (cursor != null && isCursorInBody(cursor)) {
   String uri = CTSdtBlock.type.getName().getNamespaceURI();
   String localPart = "sdt";
   cursor.beginElement(localPart, uri);
   cursor.toParent();
   block = (CTSdtBlock) cursor.getObject(); 
  } else {
   block = this.getDocument().getBody().addNewSdt();
  }
  TOC toc = new TOC(block);
  int bookmarkId = 0;
  String tocIdPrefix = "123456";
  for (XWPFParagraph par : paragraphs) {
   String parStyleId = par.getStyle();
   if (parStyleId != null && parStyleId.toLowerCase().startsWith(headingStyleIdPrefix.toLowerCase())) {
    try {
     int level = Integer.parseInt(parStyleId.substring(headingStyleIdPrefix.length()));
     par.getCTP().addNewBookmarkStart();
     par.getCTP().getBookmarkStartArray(0).setId(BigInteger.valueOf(bookmarkId));
     par.getCTP().getBookmarkStartArray(0).setName("_Toc" + tocIdPrefix + bookmarkId);
     par.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(bookmarkId));
     toc.addRow(level, par.getText(), 1, "" + tocIdPrefix + bookmarkId);
     bookmarkId++;
    } catch (Exception e) {
     LOG.log(POILogger.ERROR, "can't create TOC item", e);
    }
   }
  }
  recreateBodyElementLists();
 }

 protected void recreateBodyElementLists() {
  bodyElements = new ArrayList<>();
  paragraphs = new ArrayList<>();
  tables = new ArrayList<>();
  contentControls = new ArrayList<>();
  // parse the document with cursor and add
  // the XmlObject to its lists
  XmlCursor docCursor = this.getDocument().newCursor();
  docCursor.selectPath("./*");
  while (docCursor.toNextSelection()) {
   XmlObject o = docCursor.getObject();
   if (o instanceof CTBody) {
    XmlCursor bodyCursor = o.newCursor();
    bodyCursor.selectPath("./*");
    while (bodyCursor.toNextSelection()) {
     XmlObject bodyObj = bodyCursor.getObject();
     if (bodyObj instanceof CTP) {
      XWPFParagraph p = new XWPFParagraph((CTP) bodyObj, this);
      bodyElements.add(p);
      paragraphs.add(p);
     } else if (bodyObj instanceof CTTbl) {
      XWPFTable t = new XWPFTable((CTTbl) bodyObj, this);
      bodyElements.add(t);
      tables.add(t);
     } else if (bodyObj instanceof CTSdtBlock) {
      XWPFSDT c = new XWPFSDT((CTSdtBlock) bodyObj, this);
      bodyElements.add(c);
      contentControls.add(c);
     }
    }
    bodyCursor.dispose();
   }
  }
  docCursor.dispose();
 }
 
 public List<XWPFSDT> getContentControls() {
  return Collections.unmodifiableList(contentControls);
 }
            
 private boolean isCursorInBody(XmlCursor cursor) {
  XmlCursor verify = cursor.newCursor();
  verify.toParent();
  boolean result = (verify.getObject() == getDocument().getBody());
  verify.dispose();
  return result;
 }
}
import java.io.*;
导入java.math.biginger;
导入org.apache.poi.util.POILogFactory;
导入org.apache.poi.util.POILogger;
导入org.apache.poi.xwpf.usermodel.*;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
导入org.apache.xmlbeans.XmlCursor;
导入org.apache.xmlbeans.XmlObject;
导入java.util.List;
导入java.util.ArrayList;
导入java.util.Collections;
公共类MyXWPFDocument扩展了XWPFDocument{
私有静态最终POILogger LOG=POILogFactory.getLogger(XWPFDocument.class);
公共MyXWPFDocument(InputStream is)引发IOException{
超级(is);
}
public void createTOC(XmlCursor游标,字符串头样式idprefix){
CTSdtBlock block=null;
if(游标!=null&&isCursorInBody(游标)){
字符串uri=CTSdtBlock.type.getName().getNamespaceURI();
字符串localPart=“sdt”;
cursor.beginElement(localPart,uri);
cursor.toParent();
block=(CTSdtBlock)cursor.getObject();
}否则{
block=this.getDocument().getBody().addNewSdt();
}
TOC TOC=新TOC(块);
int bookmark id=0;
字符串tocidrefix=“123456”;
对于(XWPF段落PAR:段落){
String PasSyLID= PAR.GETSyle();
if(parStyleId!=null&&parStyleId.toLowerCase().startsWith(headingStyleIdPrefix.toLowerCase()){
试一试{
int level=Integer.parseInt(parStyleId.substring(headingStyleIdPrefix.length());
PAR.GETCTP().AdvNeBooMARKSTART();
GoBookMaskTARTARY(0).SETID(BigTime.ValueOf(书签ID));
Pr.GETCTP().GoBookMaskStARTARY(0).SETNEX(“O-Toc”+ ToePixFix+书签ID);
PAR.GETCTP().AdvEngBooMKIN().SETID(BigTime.ValueOf(书签ID));
AdDrw(Apple,Par .GETTrk(),1,“+”+ ToePixFix+书签ID;
书签ID++;
}捕获(例外e){
LOG.LOG(POILogger.ERROR,“无法创建TOC项”,e);
}
}
}
重新创建BodyElementList();
}
受保护的void replaceBodyElementList(){
bodyElements=新的ArrayList();
段落=新的ArrayList();
tables=newarraylist();
contentControls=newarraylist();
//使用游标解析文档并添加
//将XmlObject添加到其列表中
X