In response to a request here is the code and instructions to compile it.
The following properties need to be added to src/codegen/extproperties.xml.
Also, for reasons unknown to me FOP will not compile correctly unless they
also appear in src/codegen/foproperties.xml.
<!--  .....BEGIN ON NEXT LINE........  -->
<!--  .....END ON PREVIOUS LINE........  -->

Add the following line to
<!--  .....BEGIN ON NEXT LINE........  -->
            foObjs.put("WritePageNumber", WritePageNumber.maker());
<!--  .....END ON PREVIOUS LINE........  -->

Here is the code for
<!--  .....BEGIN ON NEXT LINE........  -->
 * $Id:,v 1.3 2002/02/18 20:29:20 matthew Exp $
 * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
 * For details on use and redistribution please refer to the
 * LICENSE file included with these sources.

package org.apache.fop.extensions;

import org.apache.fop.render.Renderer;
import org.apache.fop.layout.*;
import org.apache.fop.datatypes.*;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.*;

public class WritePageNumber extends ExtensionObj {

    public static class Maker extends FObj.Maker {
        public FObj make(FObj parent, PropertyList propertyList) {
            return new WritePageNumber(parent, propertyList);


    public static FObj.Maker maker() {
        return new WritePageNumber.Maker();
    String id;
    String filename;
    String file;
    String root_element;
    String element_name;

    public WritePageNumber(FObj parent, PropertyList propertyList) {
        super(parent, propertyList);

    public Status layout(Area area) throws FOPException {
        if (!(area instanceof BlockArea)) {
            log.warn("write-page-number outside block area");
            return new Status(Status.OK);

        /* The name of the file where to emit the page number */
        filename ="filename").getString();
        if (this.filename == null || this.filename.equals("")){
                        log.warn("WritePageNumber filename property value required");
                        return new Status(Status.OK);

        /* file = "new | append | end", i.e. this is a new file,
        append to an existing file, or close the file to make it
        a valid xml file.  */
        this.file ="file").getString();

                /* This is so you can associate an id with the page number */ ="id").getString();
        if ( == null ||"")){
               = "not-defined-in-either-xml-or-xslt-file";

        this.root_element ="root-element").getString();
        /* If the property isn't defined or is empty give it a default
value. */
        if (this.root_element == null || this.root_element.equals("")){
                        this.root_element = "info";

        this.element_name ="element-name").getString();
        /* If the property isn't defined or is empty give it a default
value. */
        if (this.element_name == null || this.element_name.equals("")){
                        this.element_name = "x-ref";

        /* OK, now assign the actual page number to p. */
        String p = area.getPage().getFormattedNumber();

                        // Only in the case where file = "new" should a new file be 
                        BufferedWriter out = new BufferedWriter(new
                        // Insert the root element if this is a new file.
                        if ("new".equals(file)){
                                out.write("<" + root_element + ">\n");
                        // emit the element an id and the page the id is on
                        out.write("   <" + element_name + " id=\"" + + "\">" + 
p + "</" +
element_name + ">\n");
                        // Close the root element to make the file a valid xml file.
                        if ("end".equals(file)){
                                BufferedReader in = new BufferedReader(new 
                                String root;
                                root = in.readLine();
                                out.write("</" + root.substring(1));
                        } catch(IOException e){
                } catch (IOException e){
        return new Status(Status.OK);

<!--  .....END ON PREVIOUS LINE........  -->
Once all this is in place you should be able to just build FOP in the normal
way.  WritePageNumber.class will be put into the fop.jar.
To use the element place   xmlns:fop="";
in the xsl:stylesheet element and specify the element as described below.
When FOP is run you will end up with your pdf and an extra xml file.  To
make sure it is a valid xml file, make sure that the first time
WritePageNumber is used to include file="new" and that WritePageNumber
includes file="end" the last time it is used to properly close the root
element, whatever that happens to be.  The root element only has to be
specified once with file="new" if you want to use an element name other than
the default one because when file="end" is used the root element will be
read from the file being written and closed appropriately.
Finally, I am sure there are corrections that can be made to the code.  I
have not been programming in Java nearly as long as some of you in this
list, so please be kind with your critique.  Be that as it may, the code
works (with at least 0.20.4) and I think the element is rather nifty and I'd
be glad to hear if any of you use it in an interesting way.
Have fun,
   Matthew L. Avizinis <mailto:[EMAIL PROTECTED]>
Gleim Publications, Inc.
   4201 NW 95th Blvd.
 Gainesville, FL 32606
(352)-375-0772 <>

comĚputĚing (kum' pyoot ing)
1. n the art of calculating how much time you wasted and money you spent in
a doomed attempt to master a machine with a mind of it's own. --from

> -----Original Message-----
> From: Matthew L. Avizinis [mailto:[EMAIL PROTECTED]]
> Sent: Monday, July 29, 2002 3:00 PM
> Subject: FOP extension element
> Hello all,
>   I have written an FOP extension element, fop:WritePageNumber, which
> outputs the page number where the element occurs in the fo
> document.  It has
> several properties which allow to specify a filename, whether to
> start a new
> file, append to an existing file, or close the root element of an existing
> file, a root-element, child element-name, an id for the element.
> If a root element is not specified <info> is used by default.
> If a child element is not specified <x-ref> is used by default.
> file = "new | append | end"
> id = "string value"
> filename = "string value"
> So if you wrote:
> <fop:WritePageNumber filename="index.xml" file="new" root-element="index"
> element-name="indexterm" id="primary_test1"/>
> <fop:WritePageNumber filename="index.xml" element-name="indexterm"
> id="secondary_test2"/>
> <fop:WritePageNumber filename="index.xml" file="end"
> element-name="indexterm" id="secondary_test3"/>
> you could have in file index.xml (page numbers chosen arbitrarily for this
> example):
> <index>
>   <indexterm id="primary_test1">325</indexterm>
>   <indexterm id="secondary_test2">326</indexterm>
>   <indexterm id="secondary_test3">327</indexterm>
> </index>
> This has been useful for me because it allows me to process many
> chapters of
> a book individually through FOP then put them together and still
> produce an
> index and various other cross references across chapters.  It
> also allow the
> generation of a table of contents without having to use forward page
> references and thus the necessity of processing all chapters as one big
> file.
> If anyone else thinks this is something useful, I will post the code for
> review.  It's not perfect code but it works.
>    Matthew L. Avizinis <mailto:[EMAIL PROTECTED]>
> Gleim Publications, Inc.
>    4201 NW 95th Blvd.
>  Gainesville, FL 32606
> (352)-375-0772
> <>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, email: [EMAIL PROTECTED]

To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to