XFAExtractorTest.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tika.parser.pdf;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.junit.jupiter.api.Test;
import org.xml.sax.ContentHandler;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.WriteLimitReachedException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.sax.ToXMLContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
public class XFAExtractorTest {
private static final String XDP = "<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">\n" +
"<template xmlns=\"http://www.xfa.org/schema/xfa-template/3.3/\">\n" +
" <subform name=\"form1\">\n" +
" <field name=\"School_Name\">\n" +
" <?PDF_OBJR 12 0 R?>\n" +
" dropped: text directly under a field\n" +
" <assist><toolTip><p>School</p><p>Name</p></toolTip></assist>\n" +
" </field>\n" +
" <field name=\"Room_1\"><assist><toolTip> </toolTip></assist></field>\n" +
" <field><assist><toolTip>Nameless</toolTip></assist></field>\n" +
" <draw><value><text>Mount <![CDATA[Rushmore]]></text></value></draw>\n" +
" <draw><value><exData>intro<p>first</p><p></p>tail</exData></value></draw>\n" +
" <draw><value><speak> </speak></value></draw>\n" +
" <assist><toolTip>Top-level tip</toolTip></assist>\n" +
" </subform>\n" +
"</template>\n" +
"<other><field name=\"Not_A_Template_Field\"/></other>\n" +
"<xfa:datasets xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\">\n" +
" <xfa:data><form1>" +
"<School_Name>my_school</School_Name>" +
"<Room_1>my_room1</Room_1><Room_1>my_room2</Room_1>" +
"before<Unbound>inner</Unbound>after" +
"</form1></xfa:data>\n" +
"</xfa:datasets>\n" +
"</xdp:xdp>";
@Test
public void testFieldsValuesAndText() throws Exception {
String xml = extract(XDP, new ToXMLContentHandler());
String body = xml.substring(xml.indexOf("<body>") + "<body>".length(),
xml.indexOf("</body>"));
//text before a <p> merges into that paragraph; every </p> in a toolTip adds "\n"
assertEquals("<div class=\"xfa_content\"><p>Mount Rushmore</p>\n" +
"<p>introfirst</p>\n<p>tail</p>\n" +
"<p>Top-level tip</p>\n" +
"<div class=\"xfa_form\"><ol>" +
"\t<li fieldName=\"School_Name\">School\nName\n: my_school</li>\n" +
"\t<li fieldName=\"Room_1\">Room_1: my_room1</li>\n" +
"\t<li fieldName=\"Room_1\">Room_1: my_room2</li>\n" +
"\t<li fieldName=\"\">Nameless: </li>\n" +
"</ol>\n</div>\n" +
"</div>\n", body);
}
@Test
public void testMalformedIsTikaExceptionAndDivBalanced() throws Exception {
ToXMLContentHandler handler = new ToXMLContentHandler();
XHTMLContentHandler xhtml = xhtml(handler);
xhtml.startDocument();
try (InputStream is = stream("<xdp><template xmlns=\"http://www.xfa.org/schema/" +
"xfa-template/3.3/\"><text>partial</text><field")) {
assertThrows(TikaException.class,
() -> new XFAExtractor().extract(is, xhtml, new Metadata(),
new ParseContext()));
}
xhtml.endDocument();
String xml = handler.toString();
assertTrue(xml.contains("<div class=\"xfa_content\"><p>partial</p>\n</div>\n</body>"), xml);
}
@Test
public void testDownstreamExceptionPropagatesUnwrapped() {
assertThrows(WriteLimitReachedException.class,
() -> extract(XDP, new BodyContentHandler(3)));
}
private static String extract(String xdp, ContentHandler handler) throws Exception {
XHTMLContentHandler xhtml = xhtml(handler);
xhtml.startDocument();
try (InputStream is = stream(xdp)) {
new XFAExtractor().extract(is, xhtml, new Metadata(), new ParseContext());
}
xhtml.endDocument();
return handler.toString();
}
private static XHTMLContentHandler xhtml(ContentHandler handler) {
return new XHTMLContentHandler(handler, new Metadata(), new ParseContext());
}
private static InputStream stream(String xml) throws Exception {
return UnsynchronizedByteArrayInputStream.builder()
.setByteArray(xml.getBytes(StandardCharsets.UTF_8)).get();
}
}