mirror of https://github.com/apache/nifi.git
NIFI-4062 Provide an option to disable DTD validation for EvaluateXPath and EvaluateXQuery
This closes #2093. Signed-off-by: Koji Kawamura <ijokarumawak@apache.org>
This commit is contained in:
parent
02c05bc203
commit
6df112e4b1
|
@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -43,6 +44,7 @@ import javax.xml.transform.Transformer;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||||
|
import javax.xml.transform.sax.SAXSource;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
import javax.xml.xpath.XPathExpression;
|
import javax.xml.xpath.XPathExpression;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
@ -75,10 +77,14 @@ import org.apache.nifi.processor.io.InputStreamCallback;
|
||||||
import org.apache.nifi.processor.io.OutputStreamCallback;
|
import org.apache.nifi.processor.io.OutputStreamCallback;
|
||||||
import org.apache.nifi.stream.io.BufferedInputStream;
|
import org.apache.nifi.stream.io.BufferedInputStream;
|
||||||
import org.apache.nifi.stream.io.BufferedOutputStream;
|
import org.apache.nifi.stream.io.BufferedOutputStream;
|
||||||
|
import org.xml.sax.EntityResolver;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import net.sf.saxon.lib.NamespaceConstant;
|
import net.sf.saxon.lib.NamespaceConstant;
|
||||||
import net.sf.saxon.xpath.XPathEvaluator;
|
import net.sf.saxon.xpath.XPathEvaluator;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
|
import org.xml.sax.helpers.XMLReaderFactory;
|
||||||
|
|
||||||
@EventDriven
|
@EventDriven
|
||||||
@SideEffectFree
|
@SideEffectFree
|
||||||
|
@ -125,6 +131,14 @@ public class EvaluateXPath extends AbstractProcessor {
|
||||||
.defaultValue(RETURN_TYPE_AUTO)
|
.defaultValue(RETURN_TYPE_AUTO)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor VALIDATE_DTD = new PropertyDescriptor.Builder()
|
||||||
|
.name("Validate DTD")
|
||||||
|
.description("Specifies whether or not the XML content should be validated against the DTD.")
|
||||||
|
.required(true)
|
||||||
|
.allowableValues("true", "false")
|
||||||
|
.defaultValue("true")
|
||||||
|
.build();
|
||||||
|
|
||||||
public static final Relationship REL_MATCH = new Relationship.Builder()
|
public static final Relationship REL_MATCH = new Relationship.Builder()
|
||||||
.name("matched")
|
.name("matched")
|
||||||
.description("FlowFiles are routed to this relationship "
|
.description("FlowFiles are routed to this relationship "
|
||||||
|
@ -162,6 +176,7 @@ public class EvaluateXPath extends AbstractProcessor {
|
||||||
final List<PropertyDescriptor> properties = new ArrayList<>();
|
final List<PropertyDescriptor> properties = new ArrayList<>();
|
||||||
properties.add(DESTINATION);
|
properties.add(DESTINATION);
|
||||||
properties.add(RETURN_TYPE);
|
properties.add(RETURN_TYPE);
|
||||||
|
properties.add(VALIDATE_DTD);
|
||||||
this.properties = Collections.unmodifiableList(properties);
|
this.properties = Collections.unmodifiableList(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +234,24 @@ public class EvaluateXPath extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
final ComponentLog logger = getLogger();
|
final ComponentLog logger = getLogger();
|
||||||
|
final XMLReader xmlReader;
|
||||||
|
|
||||||
|
try {
|
||||||
|
xmlReader = XMLReaderFactory.createXMLReader();
|
||||||
|
} catch (SAXException e) {
|
||||||
|
logger.error("Error while constructing XMLReader {}", new Object[]{e});
|
||||||
|
throw new ProcessException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.getProperty(VALIDATE_DTD).asBoolean()) {
|
||||||
|
xmlReader.setEntityResolver(new EntityResolver() {
|
||||||
|
@Override
|
||||||
|
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
|
||||||
|
return new InputSource(new StringReader(""));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final XPathFactory factory = factoryRef.get();
|
final XPathFactory factory = factoryRef.get();
|
||||||
final XPathEvaluator xpathEvaluator = (XPathEvaluator) factory.newXPath();
|
final XPathEvaluator xpathEvaluator = (XPathEvaluator) factory.newXPath();
|
||||||
final Map<String, XPathExpression> attributeToXPathMap = new HashMap<>();
|
final Map<String, XPathExpression> attributeToXPathMap = new HashMap<>();
|
||||||
|
@ -277,7 +310,8 @@ public class EvaluateXPath extends AbstractProcessor {
|
||||||
@Override
|
@Override
|
||||||
public void process(final InputStream rawIn) throws IOException {
|
public void process(final InputStream rawIn) throws IOException {
|
||||||
try (final InputStream in = new BufferedInputStream(rawIn)) {
|
try (final InputStream in = new BufferedInputStream(rawIn)) {
|
||||||
final List<Source> rootList = (List<Source>) slashExpression.evaluate(new InputSource(in), NODESET);
|
final List<Source> rootList = (List<Source>) slashExpression.evaluate(new SAXSource(xmlReader,
|
||||||
|
new InputSource(in)), NODESET);
|
||||||
sourceRef.set(rootList.get(0));
|
sourceRef.set(rootList.get(0));
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
error.set(e);
|
error.set(e);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -68,6 +69,7 @@ import org.apache.nifi.processor.util.StandardValidators;
|
||||||
import org.apache.nifi.stream.io.BufferedInputStream;
|
import org.apache.nifi.stream.io.BufferedInputStream;
|
||||||
import org.apache.nifi.stream.io.BufferedOutputStream;
|
import org.apache.nifi.stream.io.BufferedOutputStream;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.EntityResolver;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import net.sf.saxon.s9api.DOMDestination;
|
import net.sf.saxon.s9api.DOMDestination;
|
||||||
|
@ -79,6 +81,9 @@ import net.sf.saxon.s9api.XQueryExecutable;
|
||||||
import net.sf.saxon.s9api.XdmItem;
|
import net.sf.saxon.s9api.XdmItem;
|
||||||
import net.sf.saxon.s9api.XdmNode;
|
import net.sf.saxon.s9api.XdmNode;
|
||||||
import net.sf.saxon.s9api.XdmValue;
|
import net.sf.saxon.s9api.XdmValue;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
|
import org.xml.sax.helpers.XMLReaderFactory;
|
||||||
|
|
||||||
@EventDriven
|
@EventDriven
|
||||||
@SideEffectFree
|
@SideEffectFree
|
||||||
|
@ -148,6 +153,14 @@ public class EvaluateXQuery extends AbstractProcessor {
|
||||||
.defaultValue("false")
|
.defaultValue("false")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor VALIDATE_DTD = new PropertyDescriptor.Builder()
|
||||||
|
.name("Validate DTD")
|
||||||
|
.description("Specifies whether or not the XML content should be validated against the DTD.")
|
||||||
|
.required(true)
|
||||||
|
.allowableValues("true", "false")
|
||||||
|
.defaultValue("true")
|
||||||
|
.build();
|
||||||
|
|
||||||
public static final Relationship REL_MATCH = new Relationship.Builder()
|
public static final Relationship REL_MATCH = new Relationship.Builder()
|
||||||
.name("matched")
|
.name("matched")
|
||||||
.description("FlowFiles are routed to this relationship when the XQuery is successfully evaluated and the FlowFile "
|
.description("FlowFiles are routed to this relationship when the XQuery is successfully evaluated and the FlowFile "
|
||||||
|
@ -182,6 +195,7 @@ public class EvaluateXQuery extends AbstractProcessor {
|
||||||
properties.add(XML_OUTPUT_METHOD);
|
properties.add(XML_OUTPUT_METHOD);
|
||||||
properties.add(XML_OUTPUT_OMIT_XML_DECLARATION);
|
properties.add(XML_OUTPUT_OMIT_XML_DECLARATION);
|
||||||
properties.add(XML_OUTPUT_INDENT);
|
properties.add(XML_OUTPUT_INDENT);
|
||||||
|
properties.add(VALIDATE_DTD);
|
||||||
this.properties = Collections.unmodifiableList(properties);
|
this.properties = Collections.unmodifiableList(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +245,24 @@ public class EvaluateXQuery extends AbstractProcessor {
|
||||||
final Map<String, XQueryExecutable> attributeToXQueryMap = new HashMap<>();
|
final Map<String, XQueryExecutable> attributeToXQueryMap = new HashMap<>();
|
||||||
|
|
||||||
final Processor proc = new Processor(false);
|
final Processor proc = new Processor(false);
|
||||||
|
final XMLReader xmlReader;
|
||||||
|
|
||||||
|
try {
|
||||||
|
xmlReader = XMLReaderFactory.createXMLReader();
|
||||||
|
} catch (SAXException e) {
|
||||||
|
logger.error("Error while constructing XMLReader {}", new Object[]{e});
|
||||||
|
throw new ProcessException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.getProperty(VALIDATE_DTD).asBoolean()) {
|
||||||
|
xmlReader.setEntityResolver(new EntityResolver() {
|
||||||
|
@Override
|
||||||
|
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
|
||||||
|
return new InputSource(new StringReader(""));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final XQueryCompiler comp = proc.newXQueryCompiler();
|
final XQueryCompiler comp = proc.newXQueryCompiler();
|
||||||
|
|
||||||
for (final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet()) {
|
for (final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet()) {
|
||||||
|
@ -272,7 +304,7 @@ public class EvaluateXQuery extends AbstractProcessor {
|
||||||
public void process(final InputStream rawIn) throws IOException {
|
public void process(final InputStream rawIn) throws IOException {
|
||||||
try (final InputStream in = new BufferedInputStream(rawIn)) {
|
try (final InputStream in = new BufferedInputStream(rawIn)) {
|
||||||
XQueryEvaluator qe = slashExpression.load();
|
XQueryEvaluator qe = slashExpression.load();
|
||||||
qe.setSource(new SAXSource(new InputSource(in)));
|
qe.setSource(new SAXSource(xmlReader, new InputSource(in)));
|
||||||
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
|
||||||
dfactory.setNamespaceAware(true);
|
dfactory.setNamespaceAware(true);
|
||||||
Document dom = dfactory.newDocumentBuilder().newDocument();
|
Document dom = dfactory.newDocumentBuilder().newDocument();
|
||||||
|
|
|
@ -33,6 +33,8 @@ import org.junit.Test;
|
||||||
public class TestEvaluateXPath {
|
public class TestEvaluateXPath {
|
||||||
|
|
||||||
private static final Path XML_SNIPPET = Paths.get("src/test/resources/TestXml/xml-snippet.xml");
|
private static final Path XML_SNIPPET = Paths.get("src/test/resources/TestXml/xml-snippet.xml");
|
||||||
|
private static final Path XML_SNIPPET_EMBEDDED_DOCTYPE = Paths.get("src/test/resources/TestXml/xml-snippet-embedded-doctype.xml");
|
||||||
|
private static final Path XML_SNIPPET_NONEXISTENT_DOCTYPE = Paths.get("src/test/resources/TestXml/xml-snippet-external-doctype.xml");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAsAttribute() throws XPathFactoryConfigurationException, IOException {
|
public void testAsAttribute() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
@ -155,4 +157,72 @@ public class TestEvaluateXPath {
|
||||||
assertTrue(outXml.contains("subNode"));
|
assertTrue(outXml.contains("subNode"));
|
||||||
assertTrue(outXml.contains("Hello"));
|
assertTrue(outXml.contains("Hello"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForEmbeddedDocTypeValidation() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXPath());
|
||||||
|
testRunner.setProperty(EvaluateXPath.DESTINATION, EvaluateXPath.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXPath.RETURN_TYPE, EvaluateXPath.RETURN_TYPE_STRING);
|
||||||
|
testRunner.setProperty(EvaluateXPath.VALIDATE_DTD, "true");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_EMBEDDED_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXPath.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXPath.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForEmbeddedDocTypeValidationDisabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXPath());
|
||||||
|
testRunner.setProperty(EvaluateXPath.DESTINATION, EvaluateXPath.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXPath.RETURN_TYPE, EvaluateXPath.RETURN_TYPE_STRING);
|
||||||
|
testRunner.setProperty(EvaluateXPath.VALIDATE_DTD, "false");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_EMBEDDED_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXPath.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXPath.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailureForExternalDocTypeWithDocTypeValidationEnabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXPath());
|
||||||
|
testRunner.setProperty(EvaluateXPath.DESTINATION, EvaluateXPath.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXPath.RETURN_TYPE, EvaluateXPath.RETURN_TYPE_STRING);
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_NONEXISTENT_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXPath.REL_FAILURE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForExternalDocTypeWithDocTypeValidationDisabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXPath());
|
||||||
|
testRunner.setProperty(EvaluateXPath.DESTINATION, EvaluateXPath.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXPath.RETURN_TYPE, EvaluateXPath.RETURN_TYPE_STRING);
|
||||||
|
testRunner.setProperty(EvaluateXPath.VALIDATE_DTD, "false");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_NONEXISTENT_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXPath.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXPath.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,15 @@ import javax.xml.xpath.XPathFactoryConfigurationException;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
import org.apache.nifi.util.TestRunners;
|
import org.apache.nifi.util.TestRunners;
|
||||||
import org.junit.Ignore;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestEvaluateXQuery {
|
public class TestEvaluateXQuery {
|
||||||
|
|
||||||
private static final Path XML_SNIPPET = Paths.get("src/test/resources/TestXml/fruit.xml");
|
private static final Path XML_SNIPPET = Paths.get("src/test/resources/TestXml/fruit.xml");
|
||||||
|
private static final Path XML_SNIPPET_EMBEDDED_DOCTYPE = Paths.get("src/test/resources/TestXml/xml-snippet-embedded-doctype.xml");
|
||||||
|
private static final Path XML_SNIPPET_NONEXISTENT_DOCTYPE = Paths.get("src/test/resources/TestXml/xml-snippet-external-doctype.xml");
|
||||||
|
|
||||||
private static final String[] fruitNames = {"apple", "apple", "banana", "orange", "blueberry", "raspberry", "none"};
|
private static final String[] fruitNames = {"apple", "apple", "banana", "orange", "blueberry", "raspberry", "none"};
|
||||||
|
|
||||||
private static final String[] methods = {EvaluateXQuery.OUTPUT_METHOD_XML, EvaluateXQuery.OUTPUT_METHOD_HTML, EvaluateXQuery.OUTPUT_METHOD_TEXT};
|
private static final String[] methods = {EvaluateXQuery.OUTPUT_METHOD_XML, EvaluateXQuery.OUTPUT_METHOD_HTML, EvaluateXQuery.OUTPUT_METHOD_TEXT};
|
||||||
|
@ -65,7 +67,6 @@ public class TestEvaluateXQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("this test is failing")
|
|
||||||
@Test
|
@Test
|
||||||
public void testFormatting() throws Exception {
|
public void testFormatting() throws Exception {
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ public class TestEvaluateXQuery {
|
||||||
+ " <name>apple</name>\n"
|
+ " <name>apple</name>\n"
|
||||||
+ " <color>red</color>\n"
|
+ " <color>red</color>\n"
|
||||||
+ " </fruit>";
|
+ " </fruit>";
|
||||||
assertEquals(expectedXml, formattedResults.get(0));
|
assertEquals(spaceTrimmed(expectedXml), spaceTrimmed(formattedResults.get(0)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "html", false, false);
|
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "html", false, false);
|
||||||
|
@ -113,7 +114,7 @@ public class TestEvaluateXQuery {
|
||||||
+ " <name>apple</name>\n"
|
+ " <name>apple</name>\n"
|
||||||
+ " <color>red</color>\n"
|
+ " <color>red</color>\n"
|
||||||
+ " </fruit>";
|
+ " </fruit>";
|
||||||
assertEquals(expectedXml, formattedResults.get(0));
|
assertEquals(spaceTrimmed(expectedXml), spaceTrimmed(formattedResults.get(0)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "text", false, false);
|
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "text", false, false);
|
||||||
|
@ -123,7 +124,7 @@ public class TestEvaluateXQuery {
|
||||||
+ " apple\n"
|
+ " apple\n"
|
||||||
+ " red\n"
|
+ " red\n"
|
||||||
+ " ";
|
+ " ";
|
||||||
assertEquals(expectedXml, formattedResults.get(0));
|
assertEquals(spaceTrimmed(expectedXml), spaceTrimmed(formattedResults.get(0)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "xml", true, false);
|
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "xml", true, false);
|
||||||
|
@ -135,7 +136,7 @@ public class TestEvaluateXQuery {
|
||||||
+ " <name>apple</name>\n"
|
+ " <name>apple</name>\n"
|
||||||
+ " <color>red</color>\n"
|
+ " <color>red</color>\n"
|
||||||
+ " </fruit>\n";
|
+ " </fruit>\n";
|
||||||
assertEquals(expectedXml, formattedResults.get(0));
|
assertEquals(spaceTrimmed(expectedXml), spaceTrimmed(formattedResults.get(0)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "xml", true, true);
|
formattedResults = getFormattedResult(XML_SNIPPET, singleElementNodeQuery, "xml", true, true);
|
||||||
|
@ -146,10 +147,14 @@ public class TestEvaluateXQuery {
|
||||||
+ " <name>apple</name>\n"
|
+ " <name>apple</name>\n"
|
||||||
+ " <color>red</color>\n"
|
+ " <color>red</color>\n"
|
||||||
+ " </fruit>\n";
|
+ " </fruit>\n";
|
||||||
assertEquals(expectedXml, formattedResults.get(0));
|
assertEquals(spaceTrimmed(expectedXml), spaceTrimmed(formattedResults.get(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String spaceTrimmed(String str) {
|
||||||
|
return Arrays.stream(str.split("\n")).map(String :: trim).reduce("", String :: concat);
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> getFormattedResult(Path xml, final String xQuery, final String method, final boolean indent, final boolean omitDeclaration) throws Exception {
|
private List<String> getFormattedResult(Path xml, final String xQuery, final String method, final boolean indent, final boolean omitDeclaration) throws Exception {
|
||||||
|
|
||||||
Map<String, String> runnerProps = new HashMap<>();
|
Map<String, String> runnerProps = new HashMap<>();
|
||||||
|
@ -648,4 +653,69 @@ public class TestEvaluateXQuery {
|
||||||
}
|
}
|
||||||
testRunner.getFlowFilesForRelationship(EvaluateXQuery.REL_MATCH).get(0).assertContentEquals(XML_SNIPPET);
|
testRunner.getFlowFilesForRelationship(EvaluateXQuery.REL_MATCH).get(0).assertContentEquals(XML_SNIPPET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForEmbeddedDocTypeValidation() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXQuery());
|
||||||
|
testRunner.setProperty(EvaluateXQuery.DESTINATION, EvaluateXQuery.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXQuery.VALIDATE_DTD, "true");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_EMBEDDED_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXQuery.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXQuery.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForEmbeddedDocTypeValidationDisabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXQuery());
|
||||||
|
testRunner.setProperty(EvaluateXQuery.DESTINATION, EvaluateXQuery.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXQuery.VALIDATE_DTD, "false");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_EMBEDDED_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXQuery.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXQuery.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailureForExternalDocTypeWithDocTypeValidationEnabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXQuery());
|
||||||
|
testRunner.setProperty(EvaluateXQuery.DESTINATION, EvaluateXQuery.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_NONEXISTENT_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXQuery.REL_FAILURE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessForExternalDocTypeWithDocTypeValidationDisabled() throws XPathFactoryConfigurationException, IOException {
|
||||||
|
final TestRunner testRunner = TestRunners.newTestRunner(new EvaluateXQuery());
|
||||||
|
testRunner.setProperty(EvaluateXQuery.DESTINATION, EvaluateXQuery.DESTINATION_CONTENT);
|
||||||
|
testRunner.setProperty(EvaluateXQuery.VALIDATE_DTD, "false");
|
||||||
|
testRunner.setProperty("some.property", "/*:bundle/node/subNode[1]/value/text()");
|
||||||
|
|
||||||
|
testRunner.enqueue(XML_SNIPPET_NONEXISTENT_DOCTYPE);
|
||||||
|
testRunner.run();
|
||||||
|
|
||||||
|
testRunner.assertAllFlowFilesTransferred(EvaluateXQuery.REL_MATCH, 1);
|
||||||
|
final MockFlowFile out = testRunner.getFlowFilesForRelationship(EvaluateXQuery.REL_MATCH).get(0);
|
||||||
|
final byte[] outData = testRunner.getContentAsByteArray(out);
|
||||||
|
final String outXml = new String(outData, "UTF-8");
|
||||||
|
assertTrue(outXml.trim().equals("Hello"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE bundle
|
||||||
|
[
|
||||||
|
<!ELEMENT bundle (node)>
|
||||||
|
<!ELEMENT node (subNode*)>
|
||||||
|
<!ELEMENT subNode (value)>
|
||||||
|
<!ELEMENT value (#PCDATA)>
|
||||||
|
]>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<bundle>
|
||||||
|
<node>
|
||||||
|
<subNode>
|
||||||
|
<value>Hello</value>
|
||||||
|
</subNode>
|
||||||
|
<subNode>
|
||||||
|
<value>World!</value>
|
||||||
|
</subNode>
|
||||||
|
</node>
|
||||||
|
</bundle>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE bundle SYSTEM "non-existent-doctype.dtd">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<bundle>
|
||||||
|
<node>
|
||||||
|
<subNode>
|
||||||
|
<value>Hello</value>
|
||||||
|
</subNode>
|
||||||
|
<subNode>
|
||||||
|
<value>World!</value>
|
||||||
|
</subNode>
|
||||||
|
</node>
|
||||||
|
</bundle>
|
Loading…
Reference in New Issue