如何以编程方式绑定表docx4j中的转发器?

时间:2019-02-17 19:10:25

标签: docx4j

我了解OpenDOPE。当我以编程方式创建用中继标签包裹的段落时,就可以了。当我尝试创建用表包裹的中继器tr时,它会抛出

org.docx4j.openpackaging.exceptions.Docx4JException: Problems applying bindings

at org.docx4j.model.datastorage.BindingTraverserXSLT.traverseToBind(BindingTraverserXSLT.java:237)
at org.docx4j.model.datastorage.BindingHandler.applyBindings(BindingHandler.java:292)
at org.docx4j.model.datastorage.BindingHandler.applyBindings(BindingHandler.java:216)
at org.docx4j.Docx4J.bind(Docx4J.java:554)

但是当我保存文档然后使用Docx4J.load()进行加载然后进行绑定时,效果很好。

编辑 tr的XMLUtils.deepCopy sdtContent中出现问题

/*
         * Losing content here?
         * 
         * First, make absolutely sure that what you have is valid.
         * 

XmlUtils.marshaltoString(tbl);

的结果
<w:tbl xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram" xmlns:cppr="http://schemas.microsoft.com/office/2006/coverPageProps" xmlns:odx="http://opendope.org/xpaths" xmlns:c14="http://schemas.microsoft.com/office/drawing/2007/8/2/chart" xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:we="http://schemas.microsoft.com/office/webextensions/webextension/2010/11" xmlns:pvml="urn:schemas-microsoft-com:office:powerpoint" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:comp="http://schemas.openxmlformats.org/drawingml/2006/compatibility" xmlns:b="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:xvml="urn:schemas-microsoft-com:office:excel" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:oda="http://opendope.org/answers" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:odc="http://opendope.org/conditions" xmlns:cdr="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:odi="http://opendope.org/components" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:lc="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" xmlns:odq="http://opendope.org/questions" xmlns:wetp="http://schemas.microsoft.com/office/webextensions/taskpanes/2010/11" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid">
<w:tblPr>
    <w:tblStyle w:val="TableGrid"/>
    <w:tblW w:w="0" w:type="auto"/>
    <w:tblLook w:val="04A0"/>
</w:tblPr>
<w:tblGrid>
    <w:gridCol w:w="100"/>
</w:tblGrid>
<w:tr>
    <w:tc>
        <w:tcPr>
            <w:tcW w:w="100" w:type="dxa"/>
        </w:tcPr>
        <w:p/>
    </w:tc>
</w:tr>
<w:sdt>
    <w:sdtPr>
        <w:alias w:val="Repeat"/>
        <w:tag w:val="od:repeat=x1"/>
        <w:id w:val="2058423626"/>
    </w:sdtPr>
    <w:sdtContent>
        <w:tr>
            <w:sdt>
                <w:sdtPr>
                    <w:alias w:val=""/>
                    <w:tag w:val="od:xpath=x0"/>
                    <w:id w:val="947420646"/>
                    <w:dataBinding w:xpath="/invoice[1]/items/item[1]/name" w:storeItemID="{bb8f553d-dc92-4c50-b1cb-06e77bbe149a}"/>
                </w:sdtPr>
                <w:sdtContent>
                    <w:tc>
                        <w:p/>
                    </w:tc>
                </w:sdtContent>
            </w:sdt>
        </w:tr>
    </w:sdtContent>
</w:sdt>

1 个答案:

答案 0 :(得分:0)

在JAXB中,内容控件有不同的Java对象,具体取决于它们包装的是块级,行级,单元级还是运行级内容。这些对象都实现接口SdtElement。

类似地,SdtContent也有不同的Java对象,这取决于它们包装的是块级,行级,单元级还是运行级内容。这些对象都扩展了SdtContent。

您必须使用正确的对象,否则您会注意到,deepCopy将无法正常工作。

我已修改您的代码以使用SdtElement和SdtContent

public class ContentControlFactory {
    ObjectFactory wmlObjectFactory = getWmlObjectFactory();

    public SdtPr createSdtPr(CTDataBinding dataBinding, String tag, String alias) {
        SdtPr sdtPr = createSdtPr(tag, alias);
        sdtPr.setDataBinding(dataBinding);

        return sdtPr;
    }

    public SdtPr createSdtPr(String tag, String alias) {
        Tag t = new Tag();

        SdtPr.Alias a = new SdtPr.Alias();
        a.setVal(alias);
        t.setVal(tag);
        SdtPr sdtPr = wmlObjectFactory.createSdtPr();
        sdtPr.getRPrOrAliasOrLock().add(a);
        sdtPr.setTag(t);

        sdtPr.setId();
        return sdtPr;
    }

    public SdtElement createRepeaterControl(Xpaths.Xpath repeaterXpath, Xpaths.Xpath xpath, Object template) {

        return createSdt(
                createSdtPr("od:repeat=" + repeaterXpath.getId(), "Repeat"),
                createSdtContent(createContentControl(xpath, template))
        );
    }

    public SdtElement createRepeaterControl(Xpaths.Xpath repeaterXpath, Object template) {
        return createSdt(
                createSdtPr("od:repeat=" + repeaterXpath.getId(), "Repeat"),
                createSdtContent(template)
        );
    }

    public SdtElement createContentControl(Xpaths.Xpath xpath, Object template) {
        return createSdt(
                createSdtPr(
                        createDataBinding(xpath.getDataBinding().getXpath(), xpath.getDataBinding().getStoreItemID()),
                        "od:xpath=" + xpath.getId(), ""),
                createSdtContent(template));
    }

    public SdtContent createSdtContent(Object template) {

        System.out.println(template.getClass().getName() );
        SdtContent sdtContent = null; 
        if (template instanceof Tr) {
            sdtContent = wmlObjectFactory.createCTSdtContentRow();
        } else {
            sdtContent = wmlObjectFactory.createSdtContentBlock();

        }

        sdtContent.getContent().add(template);
        return sdtContent;
    }

    public SdtElement createConditionControl(Condition condition, Object template) {
        return createSdt(
                createSdtPr("od:condition=" + condition.getId(), ""),
                createSdtContent(template)
        );
    }

    public SdtElement createSdt(SdtPr sdtPr, SdtContent sdtContent) {
        SdtElement sdtElement = null;

        if (sdtContent instanceof CTSdtContentRow) {
            sdtElement = wmlObjectFactory.createCTSdtRow();
        } else {
            sdtElement = wmlObjectFactory.createSdtBlock();

        }

        sdtElement.setSdtPr(sdtPr);
        sdtElement.setSdtContent(sdtContent);

        return sdtElement;
    }

    public CTDataBinding createDataBinding(String xPath, String storeItemID) {
        CTDataBinding dataBinding = wmlObjectFactory.createCTDataBinding();
        dataBinding.setXpath(xPath);//xPath - это строка с XPath до XML-элемента, связанного с этим Content Control
        dataBinding.setStoreItemID(storeItemID);//storeItemID - это ID корневого XML-элемента, из которого нужно брать данные
        return dataBinding;
    }

}

并修复了tr的情况。您需要正确处理其他情况。