From ce3eac969b57fb047cc8320c179c9c896fdf4761 Mon Sep 17 00:00:00 2001 From: Tom Wetjens Date: Tue, 24 Mar 2026 14:59:26 +0100 Subject: [PATCH 1/2] #214 Trim attribute values Signed-off-by: Tom Wetjens --- .../common/xml/AttributeTrimmingFilter.java | 29 +++++++++++++++++++ .../core/common/xml/XmlSerializer.java | 25 +++++++++++----- .../core/common/xml/XmlSerializerTest.java | 7 +++++ 3 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/AttributeTrimmingFilter.java diff --git a/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/AttributeTrimmingFilter.java b/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/AttributeTrimmingFilter.java new file mode 100644 index 0000000..21367bf --- /dev/null +++ b/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/AttributeTrimmingFilter.java @@ -0,0 +1,29 @@ +package org.lfenergy.shapeshifter.core.common.xml; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.XMLFilterImpl; + +/** + * A custom XML filter that trims whitespace from the values of XML element attributes. + *

+ * This filter extends the {@link XMLFilterImpl} class, allowing it to intercept and modify + * the XML parsing process. Specifically, it overrides the {@code startElement} method to + * ensure that all attribute values are stripped of leading and trailing whitespace. + *

+ */ +class AttributeTrimmingFilter extends XMLFilterImpl { + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + var trimmedAttributes = new AttributesImpl(attributes); + + for (var i = 0; i < trimmedAttributes.getLength(); i++) { + var value = trimmedAttributes.getValue(i); + trimmedAttributes.setValue(i, value != null ? value.trim() : null); + } + + super.startElement(uri, localName, qName, trimmedAttributes); + } +} diff --git a/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializer.java b/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializer.java index c3349ca..5a53f49 100644 --- a/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializer.java +++ b/core/src/main/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializer.java @@ -5,14 +5,16 @@ package org.lfenergy.shapeshifter.core.common.xml; import jakarta.xml.bind.JAXBException; -import java.io.StringReader; -import java.io.StringWriter; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.sax.SAXSource; import org.lfenergy.shapeshifter.core.common.exception.UftpConnectorException; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.sax.SAXSource; +import java.io.StringReader; +import java.io.StringWriter; public class XmlSerializer { @@ -32,8 +34,8 @@ public String toXml(final T object) { public T fromXml(String xmlString, Class typeToUnmarshal) { try { - var xmlSource = new SAXSource(SAX_PARSER_FACTORY.newSAXParser().getXMLReader(), - new InputSource(new StringReader(xmlString))); + var xmlSource = new SAXSource(xmlReader(), + new InputSource(new StringReader(xmlString))); var unmarshaller = jaxbTools.createUnmarshaller(typeToUnmarshal); return typeToUnmarshal.cast(unmarshaller.unmarshal(xmlSource)); } catch (JAXBException | ParserConfigurationException | SAXException cause) { @@ -41,6 +43,15 @@ public T fromXml(String xmlString, Class typeToUnmarshal) { } } + private static XMLReader xmlReader() throws ParserConfigurationException, SAXException { + var parser = SAX_PARSER_FACTORY.newSAXParser(); + + var attributeTrimmingFilter = new AttributeTrimmingFilter(); + attributeTrimmingFilter.setParent(parser.getXMLReader()); + + return attributeTrimmingFilter; + } + /** * Creates a SAX Parser factory with some measures to prevent XML External Entity vulnerabilities Taken from: ... diff --git a/core/src/test/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializerTest.java b/core/src/test/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializerTest.java index 5767ed1..26d0789 100644 --- a/core/src/test/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializerTest.java +++ b/core/src/test/java/org/lfenergy/shapeshifter/core/common/xml/XmlSerializerTest.java @@ -48,6 +48,13 @@ void fromXml_PayloadMessage() { assertThat(flexRequest).isNotNull(); } + @Test + void fromXml_attributesTrailingSpaces() { + var flexRequest = xmlSerializer.fromXml("", FlexRequest.class); + + assertThat(flexRequest.getContractID()).isEqualTo("abc"); + } + @Test void fromXml_PayloadMessage_with_prolog() { var flexRequest = xmlSerializer.fromXml(XML_PROLOG + FLEX_REQUEST_XML, FlexRequest.class); From 0271aadbe8fd7c87143f81cc6e805b3aa9751b2e Mon Sep 17 00:00:00 2001 From: Tom Wetjens Date: Tue, 24 Mar 2026 15:00:58 +0100 Subject: [PATCH 2/2] #214 Update changelog Signed-off-by: Tom Wetjens --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6471f86..ab49d84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 3.5.0 +### Changed +- #214 Trim attribute values + ## 3.4.0 ### Changed - fix: #153 Invalid status code: 524