Page 1 of 1

Two different Headers from Template

PostPosted: Sun Aug 12, 2012 9:49 pm
by sandra
I'm trying to add two different Headers from my template document. Unpacking the template shows me that there are two xml files:
header2.xml //this should be the header for the first page of the document
header1.xml //this should be the header for the rest of the document

Now I'm using this code:
Code: Select all
WordprocessingMLPackage tempPkg = WordprocessingMLPackage.load(new File(templateFile));
List<SectionWrapper> sectionWrappers = tempPkg.getDocumentModel().getSections();
   
    System.out.println("Sections\n");
    for (SectionWrapper sw : sectionWrappers) {
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            System.out.println("Header");
           
            if (hfp.getFirstHeader()!=null) {
              System.out.println("-first");
              System.out.println(hfp.getFirstHeader().getPartName());           
              Part headerPart = hfp.getFirstHeader();  //header 2 for first page
              headerPart.setPartName(new PartName("/word/header2.xml"));
              //System.out.println("header2.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh1 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh1,1);
            }
            if (hfp.getDefaultHeader()!=null){
              System.out.println("-default");
              System.out.println(hfp.getFirstHeader().getPartName());
              Part headerPart = hfp.getDefaultHeader();
              headerPart.setPartName(new PartName("/word/header1.xml"));
              //header 1 should be the default header
              //System.out.println("header1.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh2 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh2,3);
            }       
    }


First of all i noticed that i get the following output on the console:

Sections

Header
-first
/word/header2.xml
-default
/word/header2.xml

But where is the header1.xml ??

And moreover this

Part headerPart = hfp.getFirstHeader(); //header 2 for first page
headerPart.setPartName(new PartName("/word/header2.xml"));
System.out.println("header2.xml:" + headerPart.getPartName() + " " + headerPart);
Relationship rh1 = mainDocumentPart.addTargetPart(headerPart);
createHeaderReference(wordMLPackage, rh1,1);

didn't work. Im getting an error:

Code: Select all
org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.save(SaveToZipFile.java:164)
   at de.fhzw.portal.studienverzeichnis.util.print.WordDocument.flush(WordDocument.java:198)
   at de.fhzw.portal.studienverzeichnis.util.print.ModulhandbuchDocxUtil.generateModulhandbuch(ModulhandbuchDocxUtil.java:135)
   at de.fhzw.portal.studienverzeichnis.print.RTFServlet.service(RTFServlet.java:99)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
   at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
   at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
   at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
   at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:428)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 21 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:428)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 23 more
Caused by: java.lang.NullPointerException
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:397)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 25 more
102109 ERROR- de.fhzw.portal.studienverzeichnis.util.print.WordDocument  - flush - Docx4JException, konnte Dokument nicht in outputStream schreiben.
org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.save(SaveToZipFile.java:164)
   at de.fhzw.portal.studienverzeichnis.util.print.WordDocument.flush(WordDocument.java:198)
   at de.fhzw.portal.studienverzeichnis.util.print.ModulhandbuchDocxUtil.generateModulhandbuch(ModulhandbuchDocxUtil.java:135)
   at de.fhzw.portal.studienverzeichnis.print.RTFServlet.service(RTFServlet.java:99)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
   at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
   at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
   at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
   at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:428)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 21 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:378)
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:428)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 23 more
Caused by: java.lang.NullPointerException
   at org.docx4j.openpackaging.io.SaveToZipFile.savePart(SaveToZipFile.java:397)
   at org.docx4j.openpackaging.io.SaveToZipFile.addPartsFromRelationships(SaveToZipFile.java:373)
   ... 25 more


I'm working very similar with the footer and that causes no error:

Code: Select all
RelationshipsPart rp = tempPkg.getMainDocumentPart().getRelationshipsPart();
    Relationship rel = rp.getRelationshipByType(Namespaces.FOOTER);
    Part footerPart = rp.getPart(rel);
    footerPart.setPartName(new PartName("/word/footer1.xml"));
    //Hinzufuegen
    Relationship rFooter = mainDocumentPart.addTargetPart(footerPart);     
    createFooterReference(wordMLPackage, rFooter);


Moreover I think the header I'm trying to add is not null ...
I have tried various types of adding the header but nothing worked well (only adding an empty one, but that is not what I want). Is it a problem if there is a picture in the header? I'm desperate and have no more ideas at the moment...

Maybe further helpfull code:
Code: Select all
  private void createHeaderReference(
                      WordprocessingMLPackage wordprocessingMLPackage,
                      Relationship relationship , int type)
                      throws InvalidFormatException {

    List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
       
    SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
    // There is always a section wrapper, but it might not contain a sectPr
    if (sectPr==null ) {
        sectPr = objectFactory.createSectPr();
        mainDocumentPart.addObject(sectPr);
        sections.get(sections.size() - 1).setSectPr(sectPr);
    }
 
    HeaderReference reference = objectFactory.createHeaderReference();
    reference.setId(relationship.getId());
    switch(type){
      case 1:
        reference.setType(HdrFtrRef.FIRST);
        break;     
      case 2:
        reference.setType(HdrFtrRef.EVEN);
        break;     
      default:
        reference.setType(HdrFtrRef.DEFAULT);
        break;
    }
    sectPr.getEGHdrFtrReferences().add(reference);
  }


I would be grateful if someone could help me with this.

Best regards
Sandra

Re: Two different Headers from Template

PostPosted: Mon Aug 13, 2012 9:04 am
by jason
The error "Failed to add parts from relationships" is possibly due to the fact that you are changing the names of parts:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
headerPart.setPartName(new PartName("/word/header2.xml"));
 
Parsed in 0.016 seconds, using GeSHi 1.0.8.4


without ensuring that for each relationship in the docx, its target still exists (target being a part name).

Also, apart from changing the part name, which most users probably shouldn't be doing, you then try to add that existing part again (addTargetPart).

If you want to change the role of an existing header, the only thing that needs to be changed is the reference to it from sectPr (your reference.setType code).

See also docx-java-f6/correct-way-to-make-first-page-header-different-t1154.html

Re: Two different Headers from Template

PostPosted: Mon Aug 13, 2012 6:36 pm
by sandra
Thank you very much for your answer Jason.
So i will adding the headers without setting the name manually.
But why does this method not find the header1.xml? Because there definitely IS a header1.xml:

Code: Select all
System.out.println("Sections\n");
    for (SectionWrapper sw : sectionWrappers) {
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            System.out.println("Header");
           
            if (hfp.getFirstHeader()!=null) {
              System.out.println("-first");
              System.out.println(hfp.getFirstHeader().getPartName());           
              Part headerPart = hfp.getFirstHeader();  //header 2 for first page
              headerPart.setPartName(new PartName("/word/header2.xml"));
              //System.out.println("header2.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh1 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh1,1);
            }
            if (hfp.getDefaultHeader()!=null){
              System.out.println("-default");
              System.out.println(hfp.getFirstHeader().getPartName());
              Part headerPart = hfp.getDefaultHeader();
              headerPart.setPartName(new PartName("/word/header1.xml"));
              //header 1 should be the default header
              //System.out.println("header1.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh2 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh2,3);
            }       
   
}

I only get header2.xml (and this one twice)

Re: Two different Headers from Template

PostPosted: Mon Aug 13, 2012 9:38 pm
by jason
Scanning your code, it is because there is both a FirstHeader, and a DefaultHeader, but in both blocks of code, you print the part name of the first header:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
 System.out.println(hfp.getFirstHeader().getPartName());
 
Parsed in 0.018 seconds, using GeSHi 1.0.8.4

Re: Two different Headers from Template

PostPosted: Wed Aug 15, 2012 9:19 pm
by sandra
Yes I see, it was my fault.

Now I have changed to Code:

Code: Select all
List<SectionWrapper> sectionWrappers = tempPkg.getDocumentModel().getSections();
   
    System.out.println("Sections\n");
    for (SectionWrapper sw : sectionWrappers) {
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            System.out.println("Header");
           
            if (hfp.getFirstHeader()!=null) {
              System.out.println("-first");   
              Part headerPart = hfp.getFirstHeader();  //header 2 ist seite 1 header
              System.out.println("header2.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh1 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh1,1);
            }
            if (hfp.getDefaultHeader()!=null){
              System.out.println("-default");
              Part headerPart = hfp.getDefaultHeader();
              System.out.println("header1.xml:" + headerPart.getPartName() + " " + headerPart);
              Relationship rh2 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh2,3);
            }
    }


But it still doesn't work. I always getting the NullPointerException mentioned above.

I also checked the link to the other forum post, but I think what I am doing here is much similar like that.
- I'm getting the first Header fom the Template
- add the Header to my new document
- create the Reference.

Same for the Default Header. But if the code in the other post works - where is my fault?

Re: Two different Headers from Template

PostPosted: Wed Aug 15, 2012 10:31 pm
by jason
Where is the NPE coming from? Is there an image in the header, because if there is, you need to handle that.

It is difficult to assist without seeing an entire source file, and in any case, in the absence of a docx4j bug, this is starting to exhaust my capacity to provide free support.

Re: Two different Headers from Template

PostPosted: Fri Aug 17, 2012 4:21 am
by sandra
Uhm,... NPE? What do you mean with NPE?

Yes, there is an image. As i wrote in my first post:

Is it a problem if there is a picture in the header?


How should I deal with that image?

Best regards
Sandra

Re: Two different Headers from Template

PostPosted: Fri Aug 17, 2012 9:25 am
by jason
NPE = Null pointer exception

If there is an image in the header, you need to handle that as well. When copying a part to a new document, you generally need to copy its relationships part, and all the parts the rels part refers to (and in the general case, do this for each of those parts, and so on).

You can run the PartsList sample on your original document to understand the structure better.

Re: Two different Headers from Template

PostPosted: Sun Aug 19, 2012 8:21 pm
by sandra
I looked at the Sample as you told me. But I'm a bit lost between Relationships, References and all this stuff.
I'm trying to write a method to add all "sub parts" of the header to my document, but i'm stucked.

I want to pass the headerParts to this method:

Code: Select all
private void addSubParts(Part mainPart){
    //get the relationships part of the document part
    //where the information is stored whether the part
    //has sub parts or not
    RelationshipsPart rp = mainPart.getRelationshipsPart(false);
    if(rp == null){
      //there are no relationships => no sub parts to add
     log.debug(mainPart.getPartName() + " has no more subs."); 
     return;
    //if there is a sub part add it
    } else{     
      try{
        for(Relationship r : rp.getRelationships().getRelationship() ) {
          //get the part the relationship belongs to
          Part part = rp.getPart(r);     
          //(1)
          Relationship rh1 = mainDocumentPart.addTargetPart(part);
          //(2)
          //addSubParts(part);
        }       
      } catch (InvalidFormatException e) {
        log.error("addSubParts - InvalidFormatException "+ e);
      } 
    }   
  }


But at (1) I don't know to which part I should add the sub Part. I guess I should add the sub Part to the headerPart in the new Document. So I was looking for something like this:
Code: Select all
mainDocumentPart.getPart(mainPart.getPartName()).addTargetPart(part);


But such a possibility doesn't exist. How can I do it right?

And the second point (2) I'm confused with the references.
Is there anything I have to do with the reference rh1 if I add this sub-Part to my header?

Adding Footer and Header to the new Document I use a method like this doing the work for me:

Code: Select all
private void createFooterReference(
        WordprocessingMLPackage wordprocessingMLPackage,
        Relationship relationship )
        throws InvalidFormatException {
 
    List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
   
    SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
    // There is always a section wrapper, but it might not contain a sectPr
    if (sectPr==null ) {
    sectPr = objectFactory.createSectPr();
    mainDocumentPart.addObject(sectPr);
    sections.get(sections.size() - 1).setSectPr(sectPr);
    }
   
    FooterReference reference = objectFactory.createFooterReference();
    reference.setId(relationship.getId());
    reference.setType(HdrFtrRef.DEFAULT);
    sectPr.getEGHdrFtrReferences().add(reference);
  }


But how can I do something similar for e.g. a ImagePart? Is it necessary?

Last but not least I want to thank you for you patience and the good work your doing here with the docx4j Projekt and this forum.
I wouldn't know what to do without your untiring help.

Many thanks in advance
Sandra

Re: Two different Headers from Template

PostPosted: Sun Aug 19, 2012 11:46 pm
by sandra
While testing my addSubPart Function I found out, that the above mentioned code seems to add the header with picture correctly. The created Document contains header1.xml and header2.xml and no error is displayed while compiling or opening the file.

But unfortunately there is only one header shown in the document. This one is correctly displayed (with picture and everything), but the header for the first page is missing... ( although the xml file is there).

This is what I'm doing at the moment:

Code: Select all
List<SectionWrapper> sectionWrappers = tempPkg.getDocumentModel().getSections();
   
    System.out.println("Sections\n");
    for (SectionWrapper sw : sectionWrappers) {
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            System.out.println("Header");
           
            if (hfp.getFirstHeader()!=null) {
              System.out.println("-first");   
              Part headerPart = hfp.getFirstHeader();               
              Relationship rh1 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh1,1);
              addSubParts(headerPart);
            }
            if (hfp.getDefaultHeader()!=null){
              System.out.println("-default");
              Part headerPart = hfp.getDefaultHeader();             
              Relationship rh2 = mainDocumentPart.addTargetPart(headerPart);     
              createHeaderReference(wordMLPackage, rh2,3);
              addSubParts(headerPart);
            }           
    }


Code: Select all
private void createHeaderReference(
                      WordprocessingMLPackage wordprocessingMLPackage,
                      Relationship relationship , int type)
                      throws InvalidFormatException {

    List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
       
    SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
    // There is always a section wrapper, but it might not contain a sectPr
    if (sectPr==null ) {
        sectPr = objectFactory.createSectPr();
        mainDocumentPart.addObject(sectPr);
        sections.get(sections.size() - 1).setSectPr(sectPr);
    }
 
    HeaderReference reference = objectFactory.createHeaderReference();
    reference.setId(relationship.getId());
    System.out.println("adding Header:"+relationship.getId());
    switch(type){
      case 1:
        reference.setType(HdrFtrRef.FIRST);
        break;     
      case 2:
        reference.setType(HdrFtrRef.EVEN);
        break;     
      default:
        reference.setType(HdrFtrRef.DEFAULT);
        break;
    }
    sectPr.getEGHdrFtrReferences().add(reference);
  }


Code: Select all
private void addSubParts(Part mainPart){
    //get the relationships part of the document part
    //where the information is stored whether the part
    //has sub parts or not
    RelationshipsPart rp = mainPart.getRelationshipsPart(false);
    if(rp == null){
      //there are no relationships => no sub parts to add
     log.debug(mainPart.getPartName() + " has no more subs."); 
     return;
    //if there is a sub part add this to the part
    } else{     
      try{
        for(Relationship r : rp.getRelationships().getRelationship() ) {
          //get the part the relationship belongs to
          Part part = rp.getPart(r);     
          //add this part TODO zum HEADER hinzufuegen nicht mainDocumentpart
          Relationship rh1 = mainDocumentPart.addTargetPart(part);
          //mainDocumentPart.getPart(mainPart.getPartName()).addTargetPart(part);
          //addSubParts(part);
        }       
      } catch (InvalidFormatException e) {
        log.error("addSubParts - InvalidFormatException "+ e);
      } 
    }
  }


And the produced output:

Header
-first
adding Header:rId4.
-default
adding Header:rId6.


Why is my Header for the first page gone?

Re: Two different Headers from Template

PostPosted: Mon Aug 20, 2012 9:24 am
by jason
If the header is gone, it is because of one of three problems:
1. it is not referenced correctly in your sectPr element
2. the rel points to the wrong header.xml file
3. the header.xml file contains the wrong content
(docx4j would complain if the rel pointed to a non-existent part)

You can find out which of these is the case by running your output through PartsList and/or unzipping to see sectPr (HeaderFooterList may also help).