This is an automated email from the ASF dual-hosted git repository. joewitt pushed a commit to branch support/nifi-1.15 in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/support/nifi-1.15 by this push: new 200538a NIFI-9399 Apply Secure Processing to TransformXml XSLT 200538a is described below commit 200538a2903be98567ecfa1981967e714920d8cd Author: exceptionfactory <exceptionfact...@apache.org> AuthorDate: Fri Nov 19 13:30:26 2021 -0600 NIFI-9399 Apply Secure Processing to TransformXml XSLT - Added XML Stream Reader processing for XSLT with external entities disabled - Removed unused XsltValidator - Upgraded Saxon-HE from 9.6.0-5 to 10.6 --- nifi-assembly/NOTICE | 2 +- .../src/main/resources/META-INF/NOTICE | 2 +- .../nifi/processors/standard/TransformXml.java | 180 ++++++++++----------- .../nifi/processors/standard/TestTransformXml.java | 46 +++++- .../test/resources/TestTransformXml/doc-node.xsl | 22 +++ .../TestTransformXml/doctype-entity-file-uri.xsl | 19 +++ .../src/test/resources/TestTransformXml/math.html | 2 +- nifi-nar-bundles/nifi-standard-bundle/pom.xml | 2 +- 8 files changed, 164 insertions(+), 111 deletions(-) diff --git a/nifi-assembly/NOTICE b/nifi-assembly/NOTICE index 095913f..baa8552 100644 --- a/nifi-assembly/NOTICE +++ b/nifi-assembly/NOTICE @@ -2108,7 +2108,7 @@ Mozilla Public License v2.0 The following binary components are provided under the Mozilla Public License v2.0. See project link for details. - (MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:9.6.0-5 - http://www.saxonica.com/) + (MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:10.6 - http://www.saxonica.com/) (MPL 2.0) Rhino (org.mozilla:rhino:jar:1.7R5 - https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Download_Rhino) ***************** diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-nar/src/main/resources/META-INF/NOTICE b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-nar/src/main/resources/META-INF/NOTICE index bd1941f..550196c 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-nar/src/main/resources/META-INF/NOTICE +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-nar/src/main/resources/META-INF/NOTICE @@ -272,7 +272,7 @@ Mozilla Public License v2.0 The following binary components are provided under the Mozilla Public License v2.0. See project link for details. - (MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:9.6.0-5 - http://www.saxonica.com/) + (MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:10.6 - http://www.saxonica.com/) ***************** Public Domain diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java index fd20b0c..b55d62a 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java @@ -33,7 +33,6 @@ import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.PropertyValue; import org.apache.nifi.components.ValidationContext; import org.apache.nifi.components.ValidationResult; -import org.apache.nifi.components.Validator; import org.apache.nifi.components.resource.ResourceCardinality; import org.apache.nifi.components.resource.ResourceType; import org.apache.nifi.expression.AttributeExpression; @@ -49,26 +48,28 @@ import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.ProcessorInitializationContext; import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.exception.ProcessException; -import org.apache.nifi.processor.io.StreamCallback; import org.apache.nifi.processor.util.StandardValidators; +import org.apache.nifi.security.xml.XmlUtils; import org.apache.nifi.util.StopWatch; -import org.apache.nifi.util.Tuple; import javax.xml.XMLConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; +import java.io.Reader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -78,14 +79,13 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; @EventDriven @SideEffectFree @SupportsBatching @Tags({"xml", "xslt", "transform"}) @InputRequirement(Requirement.INPUT_REQUIRED) -@CapabilityDescription("Applies the provided XSLT file to the flowfile XML payload. A new FlowFile is created " +@CapabilityDescription("Applies the provided XSLT file to the FlowFile XML payload. A new FlowFile is created " + "with transformed content and is routed to the 'success' relationship. If the XSL transform " + "fails, the original FlowFile is routed to the 'failure' relationship") @DynamicProperty(name = "An XSLT transform parameter name", value = "An XSLT transform parameter value", @@ -95,7 +95,7 @@ public class TransformXml extends AbstractProcessor { public static final PropertyDescriptor XSLT_FILE_NAME = new PropertyDescriptor.Builder() .name("XSLT file name") - .description("Provides the name (including full path) of the XSLT file to apply to the flowfile XML content." + .description("Provides the name (including full path) of the XSLT file to apply to the FlowFile XML content." + "One of the 'XSLT file name' and 'XSLT Lookup' properties must be defined.") .required(false) .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES) @@ -174,8 +174,6 @@ public class TransformXml extends AbstractProcessor { private Set<Relationship> relationships; private LoadingCache<String, Templates> cache; - private static AtomicReference<LookupService<String>> lookupService = new AtomicReference<LookupService<String>>(null); - @Override protected void init(final ProcessorInitializationContext context) { final List<PropertyDescriptor> properties = new ArrayList<>(); @@ -212,7 +210,7 @@ public class TransformXml extends AbstractProcessor { PropertyValue controller = validationContext.getProperty(XSLT_CONTROLLER); PropertyValue key = validationContext.getProperty(XSLT_CONTROLLER_KEY); - if((filename.isSet() && controller.isSet()) + if ((filename.isSet() && controller.isSet()) || (!filename.isSet() && !controller.isSet())) { results.add(new ValidationResult.Builder() .valid(false) @@ -221,7 +219,7 @@ public class TransformXml extends AbstractProcessor { .build()); } - if(controller.isSet() && !key.isSet()) { + if (controller.isSet() && !key.isSet()) { results.add(new ValidationResult.Builder() .valid(false) .subject(XSLT_CONTROLLER_KEY.getDisplayName()) @@ -229,7 +227,7 @@ public class TransformXml extends AbstractProcessor { .build()); } - if(controller.isSet()) { + if (controller.isSet()) { final LookupService<String> lookupService = validationContext.getProperty(XSLT_CONTROLLER).asControllerService(StringLookupService.class); final Set<String> requiredKeys = lookupService.getRequiredKeys(); if (requiredKeys == null || requiredKeys.size() != 1) { @@ -256,31 +254,6 @@ public class TransformXml extends AbstractProcessor { .build(); } - private Templates newTemplates(final ProcessContext context, final String path) throws TransformerConfigurationException, LookupFailureException { - final Boolean secureProcessing = context.getProperty(SECURE_PROCESSING).asBoolean(); - TransformerFactory factory = TransformerFactory.newInstance(); - final boolean isFilename = context.getProperty(XSLT_FILE_NAME).isSet(); - - if (secureProcessing) { - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - // don't be overly DTD-unfriendly forcing http://apache.org/xml/features/disallow-doctype-decl - factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-parameter-entities", false); - factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-general-entities", false); - } - - if(isFilename) { - return factory.newTemplates(new StreamSource(path)); - } else { - final String coordinateKey = lookupService.get().getRequiredKeys().iterator().next(); - final Optional<String> attributeValue = lookupService.get().lookup(Collections.singletonMap(coordinateKey, path)); - if (attributeValue.isPresent() && StringUtils.isNotBlank(attributeValue.get())) { - return factory.newTemplates(new StreamSource(new ByteArrayInputStream(attributeValue.get().getBytes(StandardCharsets.UTF_8)))); - } else { - throw new TransformerConfigurationException("No XSLT definition is associated to " + path + " in the lookup controller service."); - } - } - } - @OnScheduled public void onScheduled(final ProcessContext context) { final ComponentLog logger = getLogger(); @@ -290,13 +263,13 @@ public class TransformXml extends AbstractProcessor { if (cacheSize > 0) { CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder().maximumSize(cacheSize); if (cacheTTL > 0) { - cacheBuilder = cacheBuilder.expireAfterAccess(cacheTTL, TimeUnit.SECONDS); + cacheBuilder.expireAfterAccess(cacheTTL, TimeUnit.SECONDS); } cache = cacheBuilder.build( new CacheLoader<String, Templates>() { @Override - public Templates load(String path) throws TransformerConfigurationException, LookupFailureException { + public Templates load(final String path) throws TransformerConfigurationException, LookupFailureException { return newTemplates(context, path); } }); @@ -313,86 +286,95 @@ public class TransformXml extends AbstractProcessor { return; } - final ComponentLog logger = getLogger(); final StopWatch stopWatch = new StopWatch(true); final String path = context.getProperty(XSLT_FILE_NAME).isSet() ? context.getProperty(XSLT_FILE_NAME).evaluateAttributeExpressions(original).getValue() : context.getProperty(XSLT_CONTROLLER_KEY).evaluateAttributeExpressions(original).getValue(); - final Boolean indentOutput = context.getProperty(INDENT_OUTPUT).asBoolean(); - lookupService.set(context.getProperty(XSLT_CONTROLLER).asControllerService(LookupService.class)); try { - FlowFile transformed = session.write(original, new StreamCallback() { - @Override - public void process(final InputStream rawIn, final OutputStream out) throws IOException { - try (final InputStream in = new BufferedInputStream(rawIn)) { - final Templates templates; - if (cache != null) { - templates = cache.get(path); - } else { - templates = newTemplates(context, path); - } + final FlowFile transformed = session.write(original, (inputStream, outputStream) -> { + try (final InputStream bufferedInputStream = new BufferedInputStream(inputStream)) { + final Templates templates; + if (cache == null) { + templates = newTemplates(context, path); + } else { + templates = cache.get(path); + } - final Transformer transformer = templates.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, (indentOutput ? "yes" : "no")); + final Transformer transformer = templates.newTransformer(); + final String indentProperty = context.getProperty(INDENT_OUTPUT).asBoolean() ? "yes" : "no"; + transformer.setOutputProperty(OutputKeys.INDENT, indentProperty); - // pass all dynamic properties to the transformer - for (final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet()) { - if (entry.getKey().isDynamic()) { - String value = context.newPropertyValue(entry.getValue()).evaluateAttributeExpressions(original).getValue(); - transformer.setParameter(entry.getKey().getName(), value); - } + // pass all dynamic properties to the transformer + for (final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet()) { + if (entry.getKey().isDynamic()) { + String value = context.newPropertyValue(entry.getValue()).evaluateAttributeExpressions(original).getValue(); + transformer.setParameter(entry.getKey().getName(), value); } - - // use a StreamSource with Saxon - StreamSource source = new StreamSource(in); - StreamResult result = new StreamResult(out); - transformer.transform(source, result); - } catch (final Exception e) { - throw new IOException(e); } + + final Source source = new StreamSource(bufferedInputStream); + final Result result = new StreamResult(outputStream); + transformer.transform(source, result); + } catch (final Exception e) { + throw new IOException(String.format("XSLT Source Path [%s] Transform Failed", path), e); } }); session.transfer(transformed, REL_SUCCESS); session.getProvenanceReporter().modifyContent(transformed, stopWatch.getElapsed(TimeUnit.MILLISECONDS)); - logger.info("Transformed {}", new Object[]{original}); - } catch (ProcessException e) { - logger.error("Unable to transform {} due to {}", new Object[]{original, e}); + getLogger().info("Transformation Completed {}", original); + } catch (final ProcessException e) { + getLogger().error("Transformation Failed", original, e); session.transfer(original, REL_FAILURE); } } - @SuppressWarnings("unused") - private static final class XsltValidator implements Validator { + @SuppressWarnings("unchecked") + private Templates newTemplates(final ProcessContext context, final String path) throws TransformerConfigurationException, LookupFailureException { + final boolean secureProcessing = context.getProperty(SECURE_PROCESSING).asBoolean(); + final TransformerFactory transformerFactory = getTransformerFactory(secureProcessing); + final LookupService<String> lookupService = context.getProperty(XSLT_CONTROLLER).asControllerService(LookupService.class); + final boolean filePath = context.getProperty(XSLT_FILE_NAME).isSet(); + final StreamSource templateSource = getTemplateSource(lookupService, path, filePath); + final Source configuredTemplateSource = secureProcessing ? getSecureSource(templateSource) : templateSource; + return transformerFactory.newTemplates(configuredTemplateSource); + } - private volatile Tuple<String, ValidationResult> cachedResult; + private TransformerFactory getTransformerFactory(final boolean secureProcessing) throws TransformerConfigurationException { + final TransformerFactory factory = TransformerFactory.newInstance(); + if (secureProcessing) { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-parameter-entities", false); + factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-general-entities", false); + } + return factory; + } - @Override - public ValidationResult validate(final String subject, final String input, final ValidationContext validationContext) { - final Tuple<String, ValidationResult> lastResult = this.cachedResult; - if (lastResult != null && lastResult.getKey().equals(input)) { - return lastResult.getValue(); + private StreamSource getTemplateSource(final LookupService<String> lookupService, final String path, final boolean filePath) throws LookupFailureException { + final StreamSource streamSource; + if (filePath) { + streamSource = new StreamSource(path); + } else { + final String coordinateKey = lookupService.getRequiredKeys().iterator().next(); + final Map<String, Object> coordinates = Collections.singletonMap(coordinateKey, path); + final Optional<String> foundSource = lookupService.lookup(coordinates); + if (foundSource.isPresent() && StringUtils.isNotBlank(foundSource.get())) { + final String source = foundSource.get(); + final Reader reader = new StringReader(source); + streamSource = new StreamSource(reader); } else { - String error = null; - final File stylesheet = new File(input); - final TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl(); - final StreamSource styleSource = new StreamSource(stylesheet); - - try { - tFactory.newTransformer(styleSource); - } catch (final Exception e) { - error = e.toString(); - } - - this.cachedResult = new Tuple<>(input, new ValidationResult.Builder() - .input(input) - .subject(subject) - .valid(error == null) - .explanation(error) - .build()); - return this.cachedResult.getValue(); + throw new LookupFailureException(String.format("XSLT Source Path [%s] not found in Lookup Service", path)); } } + return streamSource; } + private Source getSecureSource(final StreamSource streamSource) throws TransformerConfigurationException { + try { + final XMLStreamReader streamReader = XmlUtils.createSafeReader(streamSource); + return new StAXSource(streamReader); + } catch (final XMLStreamException e) { + throw new TransformerConfigurationException("XSLT Source Stream Reader creation failed", e); + } + } } \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java index 3d5f1e0..8bcef7a 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java @@ -17,7 +17,6 @@ package org.apache.nifi.processors.standard; import java.io.BufferedReader; -import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; @@ -36,14 +35,14 @@ import org.junit.Test; public class TestTransformXml { @Test - public void testStylesheetNotFound() throws IOException { + public void testStylesheetNotFound() { final TestRunner controller = TestRunners.newTestRunner(TransformXml.class); controller.setProperty(TransformXml.XSLT_FILE_NAME, "/no/path/to/math.xsl"); controller.assertNotValid(); } @Test - public void testNonXmlContent() throws IOException { + public void testNonXmlContent() { final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); runner.setProperty(TransformXml.XSLT_FILE_NAME, "src/test/resources/TestTransformXml/math.xsl"); @@ -89,10 +88,10 @@ public class TestTransformXml { builder.append("<data>\n"); try(BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(new File("src/test/resources/TestTransformXml/tokens.csv"))))){ + new FileInputStream("src/test/resources/TestTransformXml/tokens.csv")))){ - String line = null; + String line; while ((line = reader.readLine()) != null) { builder.append(line).append("\n"); } @@ -144,7 +143,7 @@ public class TestTransformXml { } @Test - public void testTransformBothControllerFileNotValid() throws IOException, InitializationException { + public void testTransformBothControllerFileNotValid() throws InitializationException { final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); runner.setProperty(TransformXml.XSLT_FILE_NAME, "src/test/resources/TestTransformXml/math.xsl"); @@ -159,14 +158,14 @@ public class TestTransformXml { } @Test - public void testTransformNoneControllerFileNotValid() throws IOException, InitializationException { + public void testTransformNoneControllerFileNotValid() { final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); runner.setProperty(TransformXml.CACHE_SIZE, "0"); runner.assertNotValid(); } @Test - public void testTransformControllerNoKey() throws IOException, InitializationException { + public void testTransformControllerNoKey() throws InitializationException { final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); final SimpleKeyValueLookupService service = new SimpleKeyValueLookupService(); @@ -267,4 +266,35 @@ public class TestTransformXml { transformed.assertContentEquals(expectedContent); } + @Test + public void testTransformSecureProcessingEnabledXmlWithEntity() { + final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); + runner.setProperty(TransformXml.XSLT_FILE_NAME, "src/test/resources/TestTransformXml/doc-node.xsl"); + runner.setProperty(TransformXml.INDENT_OUTPUT, Boolean.FALSE.toString()); + + final String input = "<!DOCTYPE doc [<!ENTITY uri SYSTEM \"http://127.0.0.1\" >]><doc>&uri;</doc>"; + runner.enqueue(input); + runner.run(); + + runner.assertAllFlowFilesTransferred(TransformXml.REL_SUCCESS); + final MockFlowFile transformed = runner.getFlowFilesForRelationship(TransformXml.REL_SUCCESS).get(0); + + final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><doc xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"/>"; + transformed.assertContentEquals(expected); + } + + @Test + public void testTransformSecureProcessingEnabledXslWithEntity() throws IOException { + final TestRunner runner = TestRunners.newTestRunner(new TransformXml()); + runner.setProperty(TransformXml.XSLT_FILE_NAME, "src/test/resources/TestTransformXml/doctype-entity-file-uri.xsl"); + runner.setProperty(TransformXml.INDENT_OUTPUT, Boolean.FALSE.toString()); + + runner.enqueue(Paths.get("src/test/resources/TestTransformXml/doctype-entity-file-uri.xsl")); + runner.run(); + + runner.assertAllFlowFilesTransferred(TransformXml.REL_SUCCESS); + final MockFlowFile transformed = runner.getFlowFilesForRelationship(TransformXml.REL_SUCCESS).get(0); + + transformed.assertContentEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + } } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doc-node.xsl b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doc-node.xsl new file mode 100644 index 0000000..18c8e18 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doc-node.xsl @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xsl:template match="doc"> + <doc><xsl:value-of select="node()"/></doc> + </xsl:template> +</xsl:stylesheet> diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doctype-entity-file-uri.xsl b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doctype-entity-file-uri.xsl new file mode 100644 index 0000000..12ce5c5 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/doctype-entity-file-uri.xsl @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<!DOCTYPE stylesheet [<!ENTITY % uri SYSTEM 'http://127.0.0.1'> %uri;]> +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema"/> \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/math.html b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/math.html index 254d6a3..129ed34 100755 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/math.html +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/math.html @@ -1,4 +1,4 @@ -<HTML xmlns:xs="http://www.w3.org/2001/XMLSchema"> +<!DOCTYPE HTML><HTML xmlns:xs="http://www.w3.org/2001/XMLSchema"> <H1>Test for mod</H1> <HR> <P>Should say "1": 1</P> diff --git a/nifi-nar-bundles/nifi-standard-bundle/pom.xml b/nifi-nar-bundles/nifi-standard-bundle/pom.xml index 792334e..f69c089 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/pom.xml +++ b/nifi-nar-bundles/nifi-standard-bundle/pom.xml @@ -233,7 +233,7 @@ <dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> - <version>9.6.0-5</version> + <version>10.6</version> </dependency> <dependency> <groupId>joda-time</groupId>