Page 1 of 1

HTML to docx: restartList

PostPosted: Mon Dec 21, 2009 4:15 pm
by pro-tbl
2. problem in multiple OL or UL.

Before explaining the problem u need to know abt the way i am handling List.

here is the code snippet in XSLT,

Code: Select all
<xsl:when test="name() = 'ol' or name() = 'ul'">
        <xsl:if test="generate-id() = generate-id($cnode/ancestor::ol[last()]) or generate-id() = generate-id($cnode/ancestor::ul[last()])">
        <xsl:call-template name="list"/>
        </xsl:if>
    </xsl:when>
    <xsl:when test="name() = 'li'">
        <xsl:if test="generate-id() = generate-id($cnode/ancestor::li[position() = 1])">
        <w:pStyle w:val="ListParagraph"/>

        <xsl:variable name="newNumId" select="EH:getNumId($ehinst)"/>
        <xsl:variable name="alllist" select="./ancestor::*[self::ol or self::ul]"/>
        <xsl:variable name="listdepth" select="count($alllist)"/>
        <xsl:variable name="listholder" select="$alllist[$listdepth]"/>
        <xsl:variable name="lvl" select="count($listholder/ancestor::ol | $listholder/ancestor::ul)"/>

        <xsl:copy-of select="EH:addNumPr($ehinst,$wmlPackage,$newNumId,$lvl,name($listholder),$listholder/@type)"/>
        <w:rPr>
            <!-- this apply styles to list number also -->
            <xsl:for-each select="node()">
                <xsl:call-template name="handleFormatting"/>
            </xsl:for-each>
        </w:rPr>
        </xsl:if>
    </xsl:when>

<xsl:template name="list">
    <xsl:variable name="start">
        <xsl:choose>
            <xsl:when test="@start">
                <xsl:value-of select="./@start"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="1"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="type">
        <xsl:choose>
            <xsl:when test="name() = 'ol'">
                <xsl:choose>
                    <xsl:when test="@type">
                        <xsl:value-of select="./@type"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="1"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="BULLET"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="abstractNumId">
        <xsl:choose>
            <xsl:when test="name() = 'ol'">
                <xsl:value-of select="2"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="1"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="lvl" select="count(ancestor::ol | ancestor::ul)"/>
    <xsl:variable name="containerlistid" select="generate-id()"/>

    <xsl:if test="$lvl = 0">
        <xsl:variable name="newNumId" select="EH:restartList($ehinst,$wmlPackage,$abstractNumId,$lvl,$start,$type,$containerlistid)"/>
    </xsl:if>

</xsl:template>



Some java code

Code: Select all
// called when a new OL occurs
    public String restartList(WordprocessingMLPackage wmlPackage,long numId, long ilvl,long start,String type, String containerListId)
    {
        System.out.println("restartList "+numId +" // "+ilvl +" // "+start +" // "+containerListId);
        long newNumId = 0;
        try
        {
            NumberingDefinitionsPart ndp = wmlPackage.getMainDocumentPart().getNumberingDefinitionsPart();

            if(previousContainerId.equals(containerListId))
            {
                newNumId=new Long(this.numId).longValue();
            }
            else
            {
                previousContainerId=containerListId;
                newNumId=ndp.restart(numId, ilvl,start);
                this.numId=newNumId+"";
            }


            HashMap instanceListDefinitions = ndp.getInstanceListDefinitions();
            ListNumberingDefinition lnd = (ListNumberingDefinition)instanceListDefinitions.get(Long.toString(newNumId) );
            ListLevel listLvl = lnd.getLevel(ilvl+"");


            Lvl lvl=listLvl.getJaxbAbstractLvl();
            NumFmt enumTypeNode = lvl.getNumFmt();
            NumberFormat nf = GeneralUtils.getNumberFormat(type);
            enumTypeNode.setVal(nf);
            lvl.setNumFmt(enumTypeNode);
            Lvl.LvlText levelText = lvl.getLvlText();
            levelText.setVal(GeneralUtils.getLvlText(type,ilvl+1));


        }catch(Exception e){e.printStackTrace();}
        return newNumId+"";

    }


public Node addNumPr(WordprocessingMLPackage wmlPackage,long numId, long ilvl,String listtype, String numtype)
    {
        //System.out.println("addNumPr "+numId +" // "+ilvl );
        org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
        Node n=null;
        try
        {

             // Create and add <w:numPr>
            NumPr numPr =  factory.createPPrBaseNumPr();

            // The <w:ilvl> element
            Ilvl ilvlElement = factory.createPPrBaseNumPrIlvl();
            numPr.setIlvl(ilvlElement);
            ilvlElement.setVal(BigInteger.valueOf(ilvl));

            NumberingDefinitionsPart ndp = wmlPackage.getMainDocumentPart().getNumberingDefinitionsPart();
            HashMap instanceListDefinitions = ndp.getInstanceListDefinitions();
            ListNumberingDefinition lnd = (ListNumberingDefinition)instanceListDefinitions.get(this.numId );
            ListLevel listLvl = lnd.getLevel(ilvl+"");

            Lvl lvl=listLvl.getJaxbAbstractLvl();

            if(listtype.equalsIgnoreCase("ul"))
            {
                numtype="BULLET";
            }

            System.out.println("numtype "+numtype);

            NumFmt enumTypeNode = lvl.getNumFmt();
            NumberFormat nf = GeneralUtils.getNumberFormat(numtype);
            enumTypeNode.setVal(nf);
            lvl.setNumFmt(enumTypeNode);

            Lvl.LvlText levelText = lvl.getLvlText();
            levelText.setVal(GeneralUtils.getLvlText(numtype,ilvl+1));

            // The <w:numId> element
            NumId numIdElement = factory.createPPrBaseNumPrNumId();
            numPr.setNumId(numIdElement);
            numIdElement.setVal(BigInteger.valueOf(numId));
            n = XmlUtils.marshaltoW3CDomDocument(numPr);


        }catch(Exception e){e.printStackTrace();}
        return n;


    }


public static NumberFormat getNumberFormat(String type)
       {

            if(type.equals("1"))
            {
                return NumberFormat.DECIMAL;
            }
            else if (type.equals("a"))
            {
                return NumberFormat.LOWER_LETTER;
            }
            else if (type.equals("A"))
            {
                return NumberFormat.UPPER_LETTER;
            }
            else if (type.equals("i"))
            {
                return NumberFormat.LOWER_ROMAN;
            }
            else if (type.equals("I"))
            {
                return NumberFormat.UPPER_ROMAN;
            }
            else if(type.equals("BULLET"))
            {
                return NumberFormat.BULLET;
            }
            else
            {
                return NumberFormat.DECIMAL;
            }
}

public static String getLvlText(String type,Long lvl)
        {

            if(type.equals("BULLET"))
            {
                // need to set the value 
              return string;
            }
            else
            {
                return "%"+lvl+".";
            }
        }


Also i attached my numbering.xml.

Initially i keep two <w:abstractNum one is for OL and another one is for UL.

I thought restartList will duplicate the <w:abstractNum with the new changes accordingly. But it doesn't. Additionally it put some

Code: Select all
<w:num w:numId="3">
    <w:abstractNumId w:val="1"/>
    <w:lvlOverride w:ilvl="0">
        <w:startOverride w:val="1"/>
    </w:lvlOverride>
</w:num>


Which it mean no impact with the results. Also i attached my .HTML and output .DOCX for ur reference.

Get back to me in case of any further details.

Expecting ur valuable response.

Re: HTML to docx: restartList

PostPosted: Sat Jan 02, 2010 1:19 am
by jason
The NumberingDefinitionsPart method:

Code: Select all
   /**
     * For the given list numId, restart the numbering on the specified
     * level at value val.  This is done by creating a new list (ie <w:num>)
     * which uses the existing w:abstractNum.     */
    public long restart(long numId, long ilvl, long val)
       throws InvalidOperationException


is intended to allow the numbering on all lists using some specified w:abstractNum to be restarted.

As you have noticed, it does that by creating a new override (w:num), which specifies the starting number, but otherwise simply re-uses the existing abstract definition.

As far as I know, the method is functioning as intended.

If you really want to duplicate an existing w:abstractNum, you can use the XmlUtils.deepCopy method, and then allocate a new id.