gnodet commented on code in PR #11823:
URL: https://github.com/apache/maven/pull/11823#discussion_r2982270672
##########
impl/maven-xml/src/test/java/org/apache/maven/internal/xml/XmlNodeImplTest.java:
##########
@@ -715,6 +717,198 @@ public Object toInputLocation(XMLStreamReader parser) {
}
}
+ /**
+ * Verifies that when an XmlNode has xmlns:prefix declarations and prefixed
+ * attributes, the write side produces valid XML with proper namespace
handling.
+ */
+ @Test
+ void testWriteWithNamespaceDeclarationsAndPrefixedAttributes() throws
Exception {
+ String xml = """
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:mvn="http://maven.apache.org/POM/4.0.0">
+ <compilerArgs mvn:combine.children="append">
+ <arg>-Xlint:deprecation</arg>
+ </compilerArgs>
+ </project>
+ """;
+
+ XmlNode node = toXmlNode(xml);
+
+ // The xmlns:mvn declaration should be preserved in the parsed node
+ assertEquals("http://maven.apache.org/POM/4.0.0",
node.attribute("xmlns:mvn"));
+
+ // Write and re-read to verify round-trip produces valid XML
+ java.io.StringWriter writer = new java.io.StringWriter();
+ XmlService.write(node, writer);
+ String output = writer.toString();
+
+ // The output should be parseable XML (no undeclared namespace prefix
errors)
+ XmlNode reRead = toXmlNode(output);
+ assertNotNull(reRead);
+ }
+
+ /**
+ * Verifies that when a prefixed attribute has no corresponding xmlns
declaration
+ * (as happens in consumer POM transformation), the prefix is stripped on
write
+ * to produce valid XML.
+ */
+ @Test
+ void testWriteStripsOrphanedPrefixOnAttributes() throws Exception {
+ // Simulate a consumer POM scenario: mvn:combine.children exists
+ // but xmlns:mvn was lost during model transformation
+ XmlNode node = XmlNode.newBuilder()
+ .name("compilerArgs")
+ .attributes(java.util.Map.of("mvn:combine.children", "append"))
+ .children(java.util.List.of(XmlNode.newBuilder()
+ .name("arg")
+ .value("-Xlint:deprecation")
+ .build()))
+ .build();
+
+ java.io.StringWriter writer = new java.io.StringWriter();
+ XmlService.write(node, writer);
+ String output = writer.toString();
+
+ // Should not contain the undeclared mvn: prefix
+ assertFalse(output.contains("mvn:combine"), "Output should not contain
orphaned mvn: prefix");
+ // Should contain the unprefixed attribute instead
+ assertTrue(output.contains("combine.children=\"append\""), "Attribute
should be written unprefixed");
+
+ // The output should be parseable XML
+ XmlNode reRead = toXmlNode(output);
+ assertNotNull(reRead);
+ assertEquals("append", reRead.attribute("combine.children"));
+ }
+
+ /**
+ * Verifies that foreign namespace prefixed attributes round-trip correctly
+ * when the xmlns declaration is on the same element as the prefixed
attribute.
+ */
+ @Test
+ void testWriteForeignNamespaceAttributeRoundTrip() throws Exception {
+ // Build a node where xmlns:custom and custom:myattr are on the same
element
+ XmlNode node = XmlNode.newBuilder()
+ .name("compilerArgs")
+ .attributes(java.util.Map.of(
+ "xmlns:custom", "http://example.com/custom",
+ "custom:myattr", "value"))
+ .children(java.util.List.of(XmlNode.newBuilder()
+ .name("arg")
+ .value("-Xlint:deprecation")
+ .build()))
+ .build();
+
+ java.io.StringWriter writer = new java.io.StringWriter();
+ XmlService.write(node, writer);
+ String output = writer.toString();
+
+ XmlNode reRead = toXmlNode(output);
+ assertNotNull(reRead);
+ assertEquals("value", reRead.attribute("custom:myattr"));
+ assertEquals("http://example.com/custom",
reRead.attribute("xmlns:custom"));
+ }
+
+ /**
+ * Verifies that when a prefixed attribute's xmlns declaration is on a
parent
Review Comment:
_Claude Code on behalf of Guillaume Nodet_
This test reproduces the exact bug from issue #11760. Here's what happens in
the consumer POM transformation:
1. The original POM has `xmlns:mvn="http://maven.apache.org/POM/4.0.0"` on
the `<project>` element
2. Plugin configuration (e.g., `<compilerArgs
mvn:combine.children="append">`) is stored as `XmlNode` trees — the attribute
`mvn:combine.children` survives
3. During consumer POM transformation, the model is re-serialized from the
`Model` object. The `xmlns:mvn` declaration on `<project>` is **lost** (it's
not part of the Maven model)
4. When the `XmlNode` is written, `mvn:combine.children` has no
corresponding namespace declaration → "Undeclared namespace prefix" error
The choice is: produce invalid XML (crash) or strip the orphaned prefix. We
chose to strip the prefix since it's the only way to produce valid XML when the
namespace declaration has been lost. Updated the test javadoc to explain this
context.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]