diff --git a/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java b/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java
index 99af81981..b5ca4c063 100644
--- a/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java
+++ b/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java
@@ -324,7 +324,7 @@ private void writeComplexTypeDescriptor(
writeListElement(w, xmlFieldMetadata, xmlAssociationMetadata, field, getXsdType("String"));
} else if (Properties.class.getName().equals(field.getType())
|| "DOM".equals(field.getType())) {
- writePropertiesElement(w);
+ writePropertiesElement(w, "DOM".equals(field.getType()));
} else {
throw new IllegalStateException("Non-association field of a non-primitive type '"
+ field.getType() + "' for '" + field.getName() + "' in '"
@@ -408,7 +408,16 @@ private static void writeCharElement(XMLWriter w) {
w.endElement();
}
- private static void writePropertiesElement(XMLWriter w) {
+ /**
+ * Writes the complexType of a field holding free-form XML content: either a {@code java.util.Properties} or
+ * a {@code DOM} field.
+ *
+ * @param w the writer
+ * @param dom whether the field is a {@code DOM} field, in which case arbitrary attributes are allowed on the
+ * element itself, so that DOM merge hints such as {@code combine.self} or {@code combine.children}
+ * validate. A {@code Properties} element carries no attributes, so none are allowed there.
+ */
+ private static void writePropertiesElement(XMLWriter w, boolean dom) {
w.startElement("xs:complexType");
w.startElement("xs:sequence");
@@ -422,6 +431,13 @@ private static void writePropertiesElement(XMLWriter w) {
w.endElement();
+ if (dom) {
+ w.startElement("xs:anyAttribute");
+ w.addAttribute("processContents", "skip");
+
+ w.endElement();
+ }
+
w.endElement();
}
diff --git a/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/DomXsdGeneratorTest.java b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/DomXsdGeneratorTest.java
new file mode 100644
index 000000000..4b82b9932
--- /dev/null
+++ b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/DomXsdGeneratorTest.java
@@ -0,0 +1,88 @@
+package org.codehaus.modello.plugin.xsd;
+
+/*
+ * Copyright (c) 2005, Codehaus.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import javax.inject.Inject;
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import java.io.File;
+import java.util.Map;
+
+import org.codehaus.modello.AbstractModelloGeneratorTest;
+import org.codehaus.modello.ModelloException;
+import org.codehaus.modello.core.ModelloCore;
+import org.codehaus.modello.model.Model;
+import org.codehaus.plexus.testing.PlexusTest;
+import org.junit.jupiter.api.Test;
+import org.xml.sax.SAXParseException;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Checks that a DOM field accepts arbitrary attributes on its element, so that DOM merge hints such as
+ * {@code combine.self} validate, while a Properties field does not.
+ *
+ * @see issue 482
+ */
+@PlexusTest
+public class DomXsdGeneratorTest extends AbstractModelloGeneratorTest {
+ @Inject
+ private ModelloCore modello;
+
+ public DomXsdGeneratorTest() {
+ super("xsd-dom");
+ }
+
+ @Test
+ public void testDomAttributesAreAllowed() throws Throwable {
+ Model model = modello.loadModel(getXmlResourceReader("/dom.mdo"));
+
+ Map parameters = getModelloParameters("1.0.0");
+
+ modello.generate(model, "xsd", parameters);
+
+ SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = sf.newSchema(new StreamSource(new File(getOutputDirectory(), "dom-1.0.0.xsd")));
+ Validator validator = schema.newValidator();
+
+ try {
+ validator.validate(new StreamSource(getClass().getResourceAsStream("/dom.xml")));
+ } catch (SAXParseException e) {
+ throw new ModelloException("line " + e.getLineNumber() + " column " + e.getColumnNumber(), e);
+ }
+
+ try {
+ validator.validate(
+ new StreamSource(getClass().getResourceAsStream("/dom-invalid-properties-attribute.xml")));
+ fail("attributes should not be allowed on a Properties element");
+ } catch (SAXParseException e) {
+ // ok, expected exception
+ assertTrue(e.getMessage().contains("combine.self"));
+ }
+ }
+}
diff --git a/modello-plugins/modello-plugin-xsd/src/test/resources/dom-invalid-properties-attribute.xml b/modello-plugins/modello-plugin-xsd/src/test/resources/dom-invalid-properties-attribute.xml
new file mode 100644
index 000000000..e66057197
--- /dev/null
+++ b/modello-plugins/modello-plugin-xsd/src/test/resources/dom-invalid-properties-attribute.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ someValue
+
+
diff --git a/modello-plugins/modello-plugin-xsd/src/test/resources/dom.mdo b/modello-plugins/modello-plugin-xsd/src/test/resources/dom.mdo
new file mode 100644
index 000000000..cddb19a83
--- /dev/null
+++ b/modello-plugins/modello-plugin-xsd/src/test/resources/dom.mdo
@@ -0,0 +1,42 @@
+
+
+ dom
+ Dom
+
+ Model exercising the XSD generated for DOM and Properties fields.
+
+
+
+ package
+ org.codehaus.modello.test.dom
+
+
+
+
+ DomDemo
+ 1.0.0+
+
+
+ configuration
+ 1.0.0+
+ DOM
+ Free-form XML, carrying arbitrary attributes such as combine.self.
+
+
+ properties
+ 1.0.0+
+ Properties
+
+ String
+ *
+
+ Free-form XML elements, but no attributes on the container.
+
+
+
+
+
diff --git a/modello-plugins/modello-plugin-xsd/src/test/resources/dom.xml b/modello-plugins/modello-plugin-xsd/src/test/resources/dom.xml
new file mode 100644
index 000000000..f8462ab77
--- /dev/null
+++ b/modello-plugins/modello-plugin-xsd/src/test/resources/dom.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ someValue
+
+