This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new b260832016 fix encoding on Get data from XML, fixes #5222 (#6938)
b260832016 is described below

commit b260832016686919144702136abc3cd52906b671
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Apr 2 16:17:18 2026 +0200

    fix encoding on Get data from XML, fixes #5222 (#6938)
---
 .../transforms/xml/getxmldata/GetXmlData.java      |   3 +-
 .../getxmldata/LoopNodesImportProgressDialog.java  |   3 +-
 .../XmlInputFieldsImportProgressDialog.java        |   3 +-
 .../getxmldata/GetXmlDataWindows1252FileTest.java  | 128 +++++++++++++++++++++
 4 files changed, 134 insertions(+), 3 deletions(-)

diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlData.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlData.java
index b8f693df58..cb00941ea7 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlData.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlData.java
@@ -214,7 +214,8 @@ public class GetXmlData extends 
BaseTransform<GetXmlDataMeta, GetXmlDataData> {
         InputStream is = HopVfs.getInputStream(file);
         CountingInputStream countingIs = new CountingInputStream(is);
         try {
-          data.document = reader.read(countingIs, encoding);
+          reader.setEncoding(encoding);
+          data.document = reader.read(countingIs);
           dataVolumeIn = (dataVolumeIn != null ? dataVolumeIn : 0L) + 
countingIs.getCount();
         } finally {
           BaseTransform.closeQuietly(countingIs);
diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
index 1313b9e965..1f5c00a76f 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
@@ -154,7 +154,8 @@ public class LoopNodesImportProgressDialog {
       Document document = null;
       if (!Utils.isEmpty(filename)) {
         is = HopVfs.getInputStream(filename, variables);
-        document = reader.read(is, encoding);
+        reader.setEncoding(encoding);
+        document = reader.read(is);
       } else {
         if (!Utils.isEmpty(xml)) {
           document = reader.read(new StringReader(xml));
diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
index 7edca73ba9..7b761e27a6 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
@@ -175,7 +175,8 @@ public class XmlInputFieldsImportProgressDialog {
       Document document = null;
       if (!Utils.isEmpty(filename)) {
         is = HopVfs.getInputStream(filename, variables);
-        document = reader.read(is, encoding);
+        reader.setEncoding(encoding);
+        document = reader.read(is);
       } else {
         if (!Utils.isEmpty(xml)) {
           document = reader.read(new StringReader(xml));
diff --git 
a/plugins/transforms/xml/src/test/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlDataWindows1252FileTest.java
 
b/plugins/transforms/xml/src/test/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlDataWindows1252FileTest.java
new file mode 100644
index 0000000000..b35e9c31a3
--- /dev/null
+++ 
b/plugins/transforms/xml/src/test/java/org/apache/hop/pipeline/transforms/xml/getxmldata/GetXmlDataWindows1252FileTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.hop.pipeline.transforms.xml.getxmldata;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import org.apache.hop.core.HopEnvironment;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.plugins.TransformPluginType;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineHopMeta;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.engines.local.LocalPipelineEngine;
+import org.apache.hop.pipeline.transform.ITransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.hop.pipeline.transforms.dummy.DummyMeta;
+import org.apache.hop.pipeline.transforms.xml.RowTransformCollector;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+
+/**
+ * Ensures file-based parsing honors the transform encoding when the XML 
declaration omits
+ * encoding="..." (SAX must use {@link org.dom4j.io.SAXReader#setEncoding}, 
not read(InputStream,
+ * String) which treats the second argument as systemId).
+ */
+@ExtendWith(RestoreHopEnvironmentExtension.class)
+class GetXmlDataWindows1252FileTest {
+
+  @TempDir Path tempDir;
+
+  @BeforeEach
+  void init() throws Exception {
+    HopEnvironment.init();
+  }
+
+  @Test
+  void testWindows1252FileWithoutEncodingInDeclaration() throws Exception {
+    assumeTrue(Charset.isSupported("Windows-1252"));
+
+    Charset cp1252 = Charset.forName("Windows-1252");
+    // Prolog without encoding: parser must use transform encoding 
(Windows-1252).
+    // U+00E9 is single byte 0xE9 in cp1252; UTF-8 would be 0xC3 0xA9 and 
breaks if misread.
+    String logicalXml = "<?xml 
version=\"1.0\"?>\n<root><row><name>caf\u00e9</name></row></root>\n";
+    Path xmlFile = tempDir.resolve("cp1252-sample.xml");
+    Files.write(xmlFile, logicalXml.getBytes(cp1252));
+
+    String fileUri = xmlFile.toAbsolutePath().toUri().toString();
+
+    PipelineMeta pipelineMeta = new PipelineMeta();
+    pipelineMeta.setName("getxmldata-cp1252-file");
+
+    PluginRegistry registry = PluginRegistry.getInstance();
+
+    GetXmlDataMeta gxdm = new GetXmlDataMeta();
+    gxdm.setInFields(false);
+    gxdm.setAFile(false);
+    gxdm.setReadUrl(false);
+    gxdm.setEncoding("Windows-1252");
+    gxdm.setLoopXPath("root/row");
+    gxdm.setDoNotFailIfNoFile(false);
+    gxdm.setFilesList(
+        List.of(new GetXmlFileItem(fileUri, "", "", 
GetXmlDataMeta.RequiredFilesCode[1], "N")));
+
+    GetXmlDataField nameField = new GetXmlDataField("name_out");
+    nameField.setXPath("name");
+    
nameField.setElementType(GetXmlDataField.getElementTypeCode(GetXmlDataField.ELEMENT_TYPE_NODE));
+    
nameField.setType(ValueMetaFactory.getValueMetaName(IValueMeta.TYPE_STRING));
+    nameField.setFormat("");
+    nameField.setLength(-1);
+    nameField.setPrecision(-1);
+    nameField.setCurrencySymbol("");
+    nameField.setDecimalSymbol("");
+    nameField.setGroupSymbol("");
+    
nameField.setTrimType(GetXmlDataField.getTrimTypeCode(GetXmlDataField.TYPE_TRIM_NONE));
+    gxdm.setInputFields(List.of(nameField));
+
+    String getXmlPid = registry.getPluginId(TransformPluginType.class, gxdm);
+    TransformMeta getXmlTransform = new TransformMeta(getXmlPid, "get xml 
data", gxdm);
+    pipelineMeta.addTransform(getXmlTransform);
+
+    DummyMeta dm = new DummyMeta();
+    String dummyPid = registry.getPluginId(TransformPluginType.class, dm);
+    TransformMeta dummyTransform = new TransformMeta(dummyPid, "dummy", dm);
+    pipelineMeta.addTransform(dummyTransform);
+
+    pipelineMeta.addPipelineHop(new PipelineHopMeta(getXmlTransform, 
dummyTransform));
+
+    Pipeline pipeline = new LocalPipelineEngine(pipelineMeta);
+    pipeline.prepareExecution();
+
+    ITransform dummyStep = pipeline.getTransform("dummy", 0);
+    RowTransformCollector collector = new RowTransformCollector();
+    dummyStep.addRowListener(collector);
+
+    pipeline.startThreads();
+    pipeline.waitUntilFinished();
+
+    List<RowMetaAndData> rows = collector.getRowsWritten();
+    assertEquals(1, rows.size(), "Expected one row from one <row> element");
+    assertEquals("caf\u00e9", rows.get(0).getString("name_out", ""));
+  }
+}

Reply via email to