【问题标题】:ColdFusion & Java (docx4j library)ColdFusion 和 Java(docx4j 库)
【发布时间】:2012-05-30 23:10:14
【问题描述】:

我需要进行 docx 操作(查找/替换占位符和选中/取消选中复选框)。由于 ColdFusion 10 与 Java 集成得很好,我决定尝试使用 Java 库 docx4j,它基本上模仿了 OpenXML SDK(.net 平台)。

我有一个自定义文件夹中的 docx4j JAR,我通过 JavaSettings 在我的 Application.cfc 中设置了它(CF10 中的新功能,我在其他 JARS 中尝试过,它可以工作):

<cfcomponent output="false">

    <cfset this.javaSettings =
        {LoadPaths = ["/myJava/lib"], loadColdFusionClassPath = true, reloadOnChange= true, 
        watchInterval = 100, watchExtensions = "jar,class,xml"} />

</cfcomponent>

现在,我正在尝试使用这个示例:https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/samples/VariableReplace.java

但尝试调用 WordprocessingMLPackage 失败,函数 CreateObject() 说特定类不存在:

<cfset docObj = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage") />

有什么想法吗?我不是一个真正的 Java 人,但是对于 docx 操作没有太多选择。

【问题讨论】:

  • 该类不存在……嗯……好像没有找到。你确定jar文件在它应该在的地方吗?将 java 与 Coldfusion 7 一起使用,但现在看起来他们玩得很好。
  • 发布完整的堆栈跟踪。但是,我会说我不久前尝试将 docxj 与 CF9 一起使用,但无法使其工作。这与 docx4j 无关。这似乎是一个相当不错的图书馆。我刚刚在 docx4j 的依赖项和 CF 的内部库之间遇到了太多的类加载器冲突。不幸的是,我无法弄清楚如何解决它们 - 即使使用 JavaLoader。不过我还没有用 CF10 试过,所以 YMMV。
  • 使用 CF10 中的新 JavaSettings 属性,我在加载任何其他 JAR 文件和访问类时没有任何问题。我想也许是那个特定的类,所以我尝试了一个不同的类来创建一个对象(org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart),它工作得很好。我会一直玩弄它,试图真正看看我是否可以构建/操作一个文档。编辑:现在它正在工作,我认为问题是我没有提供 init() 构造函数。
  • 酷!如果类加载器问题消失了,我可能会再试一试。 现在我对 CF10 感到非常兴奋 :)

标签: java coldfusion jar docx docx4j


【解决方案1】:

好的。好像我让一切正常。我只需要弄清楚如何进行查找/替换,以及我想在 docx 文档中做的所有其他事情。到目前为止,这是我的代码,向你们展示它看起来正在工作(如果您使用的是 CF10,请确保您的 Application.cfc 看起来像原始帖子):

<cfscript>

    docPackageObj = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage").init();
    docObj = createObject("java","org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart").init();
    xmlUtilObj = createObject("java","org.docx4j.XmlUtils").init();
    wmlDocObj = createObject("java","org.docx4j.wml.Document").init();
    saveToZipFile = createObject("java","org.docx4j.openpackaging.io.SaveToZipFile").init(docPackageObj);

    strFilePath = getDirectoryFromPath(getCurrentTemplatePath()) & "testDoc.docx";

    wordMLPackage = 
        docPackageObj.load(createObject("java","java.io.File").init(javaCast("string",strFilePath)));

    documentPart = wordMLPackage.getMainDocumentPart();

    // unmarshallFromTemplate requires string input     
    strXml = xmlUtilObj.marshaltoString(documentPart.getJaxbElement(),true);

    writeDump(var="#strXml#");

</cfscript>

现在,有人知道如何将 ColdFusion 中的结构转换为哈希图(或一般的集合)吗?我认为CF中的结构实际上是util.Vector,而hashmaps是util.HashMap。我在 Docx4j 中看到的所有演示在占位符中查找/替换的示例都使用了这个:

HashMap<String, String> mappings = new HashMap<String, String>();
mappings.put("colour", "green");
mappings.put("icecream", "chocolate");

【讨论】:

  • 非常好,我迫不及待想尝试一下。至于数据类型,CF 结构是java.util.Map 对象和数组是java.util.Vector。所以我猜一个结构会起作用。有关详细信息,请参阅data type conversions 编辑:快速提问,您使用的是哪个 docx4j 版本以及您的操作系统是什么?
  • 另外,你对 jars 做了什么特别的事情还是只加载所有东西,即所有依赖项?
  • 好的,谢谢。再三考虑,您可能无法使用 CF 结构。看起来该库编码为实现(HashMap)而不是接口(Map)......呃。我讨厌他们这样做。
  • 我使用了最新的 docx4j (2.8.0) 并将 log4j-1.2.15.jar 放入与 docx4j 相同的文件夹中。我认为 log4j 是您必须拥有的唯一依赖项(对不起,我忘了提及)。 编辑 我使用的操作系统是 MS Server 2008 R2 在工作;并且看起来它使用 CF10 附带的内置 Tomcat 服务器在 Windows 7 上在家工作(使用上面的示例,它所做的只是转储文档的 XML 文本,但您必须在该文档中包含文本(它不能为空,否则会抛出字节错误)。
  • 嗯...已经有一段时间了,但我认为它需要的不仅仅是 docx4j。尽管许多库已经存在于 CF 中。所以这可能已经改变了。 (编辑)我刚刚尝试过,替换示例适用于 HashMap - 这太棒了。我很高兴你打开了这个帖子!希望我能两次投票给你:)
【解决方案2】:

您是否尝试过设置 loadColdFusionClassPath = false 而不是 true?可能与带有 CF 的某些 JAR 存在冲突。

【讨论】:

    【解决方案3】:

    (不是一个真正的新答案,但是对于 cmets 来说代码太多了..)

    这里是 docx4j VariableReplace.java 示例的完整代码

    <cfscript>
        saveToDisk = true;
        inputFilePath = ExpandPath("./docx4j/sample-docs/word/unmarshallFromTemplateExample.docx");
        outputFilePath = ExpandPath("./OUT_VariableReplace.docx");
    
        inputFile = createObject("java", "java.io.File").init(inputFilePath);
        wordMLPackage = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage").load(inputFile);
        documentPart = wordMLPackage.getMainDocumentPart();
    
        XmlUtils = createObject("java","org.docx4j.XmlUtils");
        xmlString  = XmlUtils.marshaltoString(documentPart.getJaxbElement(),true);
    
        mappings = createObject("java", "java.util.HashMap").init();
        mappings["colour"] = "green";
        mappings["icecream"] =  "chocolate";
        obj = XmlUtils.unmarshallFromTemplate(xmlString , mappings);
        documentPart.setJaxbElement(obj);
    
        if (saveToDisk) {
            saveToZipFile = createObject("java","org.docx4j.openpackaging.io.SaveToZipFile").init(wordMLPackage);
            SaveToZipFile.save( outputFilePath );
        } 
        else {
            WriteDump(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
        }
    </cfscript>
    

    【讨论】:

    • 看起来它可以工作,你只需要调整 HashMap 因为点符号不起作用。相反,这样做(我只是传入字符串变量): mappings.put("colour",#trim(variables.myColour)#); mappings.put("icecream",#trim (variables.myIcecream)#); 我注意到的一件事是,如果您完全修改文档(带有占位符的原始文档),这将导致占位符分散在多个 w:t 元素上,从而导致它不工作。我猜我们将不得不使用某种类型的 XPath 表达式?我正在挖掘样本以寻求解决方案。
    • 对不起,我的错。来晚了,贴错了版本。它应该是括号符号。 (更新)。我不确定元素。我得仔细看看发生了什么。
    • 是的,如果您编辑文档并更改内容等,它们看起来可能是单个占位符内的 w:r、w:t 和 w:rPr 元素。所以我试图找出一种可以找到/替换占位符的方法,无论它是否分散在 Word 可能会在其中折腾的多个元素中。 ://
    • 我没有太多时间查看示例。您是否尝试查看 openxml 文档/论坛?因为显然任何 xml/regex 解决方案都可以移植到 CF。
    • 我发现了它是如何使用 Open XML SDK 完成的:msdn.microsoft.com/en-us/library/bb508261.aspx 看起来他们使用了内置的正则表达式类。虽然真的找不到任何关于万无一失的 Docx4j 示例的文档。我在 Docx4j 论坛上发布了这个问题,但答案超出了我的想象。
    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多