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

veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f2bff75c  Fix namespace prefix bug in _setAttributeValue() (#771)
9f2bff75c is described below

commit 9f2bff75cf85cae235f789e69787fe572a56ec4e
Author: ckaaber <[email protected]>
AuthorDate: Sat Mar 14 09:24:45 2026 +0100

     Fix namespace prefix bug in _setAttributeValue() (#771)
    
    When setting an attribute with a QName that has a namespace,
    AxiomElementMixin._setAttributeValue() incorrectly used
    qname.getLocalPart() as the namespace prefix instead of
    qname.getPrefix(). This caused redundant namespace declarations
    like xmlns:mustUnderstand="..." on SOAP headers.
    
    The fix changes line 420 from:
      new OMNamespaceImpl(qname.getNamespaceURI(), qname.getLocalPart())
    to:
      new OMNamespaceImpl(qname.getNamespaceURI(), qname.getPrefix())
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Co-authored-by: Christian Kaaber <[email protected]>
---
 .../axiom/om/impl/mixin/AxiomElementMixin.java     |  2 +-
 .../apache/axiom/ts/soap/SOAPTestSuiteBuilder.java |  5 ++
 .../TestSetAttributeNamespacePrefix.java           | 77 ++++++++++++++++++++++
 3 files changed, 83 insertions(+), 1 deletion(-)

diff --git 
a/mixins/om-mixins/src/main/java/org/apache/axiom/om/impl/mixin/AxiomElementMixin.java
 
b/mixins/om-mixins/src/main/java/org/apache/axiom/om/impl/mixin/AxiomElementMixin.java
index d8331a7fd..7907e8a88 100644
--- 
a/mixins/om-mixins/src/main/java/org/apache/axiom/om/impl/mixin/AxiomElementMixin.java
+++ 
b/mixins/om-mixins/src/main/java/org/apache/axiom/om/impl/mixin/AxiomElementMixin.java
@@ -417,7 +417,7 @@ public abstract class AxiomElementMixin implements 
AxiomElement {
             addAttribute(
                     qname.getLocalPart(),
                     value,
-                    new OMNamespaceImpl(qname.getNamespaceURI(), 
qname.getLocalPart()));
+                    new OMNamespaceImpl(qname.getNamespaceURI(), 
qname.getPrefix()));
         }
     }
 
diff --git 
a/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/SOAPTestSuiteBuilder.java
 
b/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/SOAPTestSuiteBuilder.java
index d83f804cc..1c23295c1 100644
--- 
a/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/SOAPTestSuiteBuilder.java
+++ 
b/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/SOAPTestSuiteBuilder.java
@@ -385,6 +385,11 @@ public class SOAPTestSuiteBuilder extends 
MatrixTestSuiteBuilder {
                 new 
org.apache.axiom.ts.soap.header.TestGetHeadersToProcessWithParser(
                         metaFactory, spec));
         for (HeaderBlockAttribute attribute : 
getInstances(HeaderBlockAttribute.class)) {
+            if (attribute.isSupported(spec)) {
+                addTest(
+                        new 
org.apache.axiom.ts.soap.headerblock.TestSetAttributeNamespacePrefix(
+                                metaFactory, spec, attribute));
+            }
             if (attribute.isBoolean()) {
                 if (attribute.isSupported(spec)) {
                     for (int j = 0; j < booleanLiterals.length; j++) {
diff --git 
a/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/headerblock/TestSetAttributeNamespacePrefix.java
 
b/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/headerblock/TestSetAttributeNamespacePrefix.java
new file mode 100644
index 000000000..2e17eeaa0
--- /dev/null
+++ 
b/testing/axiom-testsuite/src/main/java/org/apache/axiom/ts/soap/headerblock/TestSetAttributeNamespacePrefix.java
@@ -0,0 +1,77 @@
+/*
+ * 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.axiom.ts.soap.headerblock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMMetaFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axiom.soap.SOAPHeaderBlock;
+import org.apache.axiom.ts.soap.HeaderBlockAttribute;
+import org.apache.axiom.ts.soap.SOAPSpec;
+import org.apache.axiom.ts.soap.SOAPTestCase;
+
+/**
+ * Tests that setting a SOAP header block attribute uses the correct namespace 
prefix from the
+ * attribute's QName, not the attribute's local name.
+ *
+ * <p>This is a regression test for a bug in {@code 
AxiomElementMixin._setAttributeValue()} where
+ * {@code qname.getLocalPart()} was incorrectly used as the namespace prefix 
instead of {@code
+ * qname.getPrefix()}. This produced redundant namespace declarations where 
the attribute name was
+ * used as its own namespace prefix (e.g. {@code xmlns:role="..."} and {@code 
role:role="..."}
+ * instead of reusing the SOAP envelope prefix).
+ */
+public class TestSetAttributeNamespacePrefix extends SOAPTestCase {
+    private final HeaderBlockAttribute attribute;
+
+    public TestSetAttributeNamespacePrefix(
+            OMMetaFactory metaFactory, SOAPSpec spec, HeaderBlockAttribute 
attribute) {
+        super(metaFactory, spec);
+        this.attribute = attribute;
+        addTestParameter("attribute", attribute.getName(spec));
+    }
+
+    @Override
+    protected void runTest() throws Throwable {
+        SOAPHeaderBlock headerBlock =
+                soapFactory.createSOAPHeaderBlock(
+                        "block", soapFactory.createOMNamespace("urn:test", 
"p"));
+
+        // Set the attribute using the appropriate setter
+        if (attribute == HeaderBlockAttribute.MUST_UNDERSTAND) {
+            headerBlock.setMustUnderstand(true);
+        } else if (attribute == HeaderBlockAttribute.ROLE) {
+            headerBlock.setRole("urn:testrole");
+        } else if (attribute == HeaderBlockAttribute.RELAY) {
+            headerBlock.setRelay(true);
+        }
+
+        String attrName = attribute.getName(spec);
+        OMAttribute attr = headerBlock.getAttribute(attribute.getQName(spec));
+        assertThat(attr).isNotNull();
+
+        OMNamespace attrNs = attr.getNamespace();
+        assertThat(attrNs).isNotNull();
+        assertThat(attrNs.getPrefix()).isNotEmpty();
+        // The namespace prefix must not be the attribute's own local name.
+        // That would indicate the prefix was derived from getLocalPart() 
instead of getPrefix().
+        assertThat(attrNs.getPrefix()).isNotEqualTo(attrName);
+    }
+}

Reply via email to