eclipse 如何在XSLT中使用ApacheTika处理RTF超链接?

qltillow  于 2023-02-15  发布在  Eclipse
关注(0)|答案(1)|浏览(147)

本问题是对以下问题的后续:What are some methods to converting RTF text nodes in XML using XSLT 2 / Saxon HE 11.3?.
在实现了所回答的解决方案之后,我对一个大数据集运行了代码,在处理所有数据的过程中,源RTF中的一个项目导致应用程序出错。
错误:

Error on line 11 column 92 of urn:from-string:  SXXP0003   Error reported by XML parser: The element type "a" must be terminated by the matching end-tag "</a>".: The element type "a" must be terminated by the matching end-tag "</a>".

我看了一下源文件xml,其中包含几个RTF HYPERLINK代码。

<SPECORMETHOD>{\rtf1\ansi\deff0\uc1\ansicpg1252\deftab720{\fonttbl{\f0\fnil\fcharset1 Arial;}{\f1\fnil\fcharset1 Times New Roman;}{\f2\fnil\fcharset1 WingDings;}}{\colortbl\red0\green0\blue0;\red255\green0\blue0;\red0\green128\blue0;\red0\green0\blue255;\red255\green255\blue0;\red255\green0\blue255;\red128\green0\blue128;\red128\green0\blue0;\red0\green255\blue0;\red0\green255\blue255;\red0\green128\blue128;\red0\green0\blue128;\red255\green255\blue255;\red192\green192\blue192;\red128\green128\blue128;\red0\green0\blue0;\red128\green128\blue0;}\wpprheadfoot1\paperw12240\paperh15840\margl720\margr720\margt720\margb720\headery720\footery720\endnhere\sectdefaultcl{\*\generator WPTools_5.17;}{\stylesheet{\s1\li0\fi0\ri0\sb0\sa0\ql\vertalt\fs20 Normal;}{\s2\li0\fi0\ri0\sb0\sa0\ql\vertalt\fs20 Default Paragraph Font;}{\s3\li0\fi0\ri0\sb0\sa0\ql\vertalt\fs20\cf3\ul\sbasedon2 Hyperlink;}}{\pard\plain\plain\f1\fs36\par\pard\plain\plain\f1\fs36\par\plain\f1\fs28\tab 10\'94Flour Tortilla\par\plain\f1\fs28\tab Caesar \f1\b\i DIP\f1\i0 : {\field{\*\fldinst{HYPERLINK "..\\\\..\\\\SAUCES\\\\Dips\\\\Dip, Caesar.doc"}}{\*\fldtitle{..\\\\..\\\\SAUCES\\\\Dips\\\\Dip, Caesar.doc}}{\fldrslt{\f1\cf3\cs103\ul\cs3 Dip, Caesar.doc\plain\f1\fs28\b}}}\par\plain\f1\fs28\tab Ripped Romaine\par\plain\f1\fs28\tab Blackened Salmon julienne\par\plain\f1\fs28\tab Shaved Red Onion\par\plain\f1\fs28\tab Julienne Tomato\par\plain\f1\fs28\tab Grated Parmesan\par\plain\f1\fs28\tab Blackening spice: {\field{\*\fldinst{HYPERLINK "..\\\\..\\\\SPICE\\\\Blackening Spice.doc"}}{\*\fldtitle{..\\\\..\\\\SPICE\\\\Blackening Spice.doc}}{\fldrslt{\f1\cf3\cs103\ul\cs3 Blackening Spice.doc\plain\f1\fs28}}}\par\pard\plain\plain\f1\fs28\par\plain\f1\fs28 Method\par\plain\f1\fs28 Procedure Text \par\pard\plain\plain\f1\fs36\par}}</SPECORMETHOD>

就我的目的而言,URL不会是一个功能组件,但为了这个RTF转换项目的实用性,可能需要什么来使超链接代码正确工作,或者将它们输出为文本以供参考?我可以处理这一问题的一种方法是在XSLT中截取元素,查找HYPERLINK代码并将其替换为常规文本。
此示例中超链接的预期输出为(仅文本):

CAESAR DIP: ..\..\SAUCES\Dips\Dip, Caesar.doc

对原始代码的唯一修改是在XSLT中处理<SPECORMETHOD>时检查空元素。

<xsl:choose>
    <xsl:when test="string-length(SPECORMETHOD) &gt; 0">
        <rtf-as-xhtml>
            <xsl:sequence select="tika:parse-rtf(SPECORMETHOD[string-length(.) &gt; 0])"/>
        </rtf-as-xhtml>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="'[EMPTY]'"/>
    </xsl:otherwise>
</xsl:choose>

我在Eclipse 2022 - 12(4.26.0)中构建了这个项目,它是一个使用Apache Tika 2.7.0和Saxon HE 11.3的Maven项目,使用Java SE 1.8。

juud5qan

juud5qan1#

我已经通过Tika运行了示例rtf,但预期的XHTML输出格式不正确:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="X-TIKA:Parsed-By" content="org.apache.tika.parser.DefaultParser" />
<meta name="X-TIKA:Parsed-By" content="org.apache.tika.parser.microsoft.rtf.RTFParser" />
<meta name="Content-Type" content="application/rtf" />
<title></title>
</head>
<body><p />
<p />
<p> 10”Flour Tortilla</p>
<p> Caesar <b><i>DIP</i>: <a href="..\\..\\SAUCES\\Dips\\Dip, Caesar.doc">Dip, Caesar.doc</b><b /></b></p>
<p><b />    Ripped Romaine</p>
<p> Blackened Salmon julienne</p>
<p> Shaved Red Onion</p>
<p> Julienne Tomato</p>
<p> Grated Parmesan</p>
<p> Blackening spice: <a href="..\\..\\SPICE\\Blackening Spice.doc">Blackening Spice.doc</a></p>
<p />
<p>Method</p>
<p>Procedure Text </p>
<p />
<p />
</body></html>

所以错误在片段<p> Caesar <b><i>DIP</i>: <a href="..\\..\\SAUCES\\Dips\\Dip, Caesar.doc">Dip, Caesar.doc</b><b /></b></p>中。
我不确定这是否是输入不正确的rtf的问题,但它看起来更像是Tia解析器和ToXmlContentHandler中的错误。
我已提出潜在问题https://issues.apache.org/jira/browse/TIKA-3972
最后,在Saxonica开发人员的帮助下(感谢MichaelKay和沃尔什),我找到了一种更好的(可能是无论如何)将Saxon与Tika解析器结合使用的方法;不使用Tika的ToXMLContentHandler()及其提供给Saxon的DocumentBuildertoString()方法结果,而是可以将Saxon的BuildingContentHandler直接传递给Tika的解析器以获得XdmNode

public static XdmNode parseRtfToHTML2(String rtf, Processor processor) throws IOException, SAXException, TikaException, URISyntaxException, SaxonApiException {
    DocumentBuilder docBuilder = processor.newDocumentBuilder();

    BuildingContentHandler handler = docBuilder.newBuildingContentHandler();

    AutoDetectParser parser = new AutoDetectParser();
    Metadata metadata = new Metadata();
    try (InputStream stream = new ByteArrayInputStream(rtf.getBytes("utf8"))) {
        parser.parse(stream, handler, metadata);
        return handler.getDocumentNode();//docBuilder.build(new StreamSource(new StringReader(handler.toString())));
    } catch (SaxonApiException e) {
        throw new RuntimeException(e);
    }
}

使用这种方法,至少在一个简短的测试中,超链接RTF示例没有抛出错误,更多上下文中的代码请参见更新的项目https://github.com/martin-honnen/SaxonTikaRtfTest1

相关问题