jaxb
  1. jaxb
  2. JAXB-999

Not well-formed XML output by Marshaller in conjunction with @XmlAnyAttribute

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.2.7
    • Fix Version/s: None
    • Component/s: runtime
    • Labels:
      None
    • Environment:

      Max OS X, JDK 1.7.0_51

      Description

      Summary

      I encountered a situation where a javax.xml.bind.Marshaller produces not well-formed XML, despite throwing no exception nor raising a validation event. The problem arises when using @XmlAnyAttribute-Annotation in a special way.

      Details

      Consider the following scenario (imports omitted):

      Test.java
      @XmlAccessorType(XmlAccessType.NONE)
      @XmlRootElement
      public class Test {
      	
      	@XmlAttribute
      	public String id;
      	
      	@XmlAnyAttribute
      	public Map<QName,String> other;
      
      }
      
      test.xsd
      <?xml version="1.0" encoding="UTF-8"?>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
          <xs:element name="test">
          	<xs:complexType>
          		<xs:anyAttribute processContents="skip"/>
          	</xs:complexType>
          </xs:element>
      </xs:schema>
      
      Main.java
      public class Main {
      
      	public static void main(String[] args) throws Exception {
      
      		Test t = new Test();
      		t.id = "5";
      		t.other = new HashMap<QName, String>();
      		t.other.put(new QName("id"), "10");
      
      		JAXBContext jc = JAXBContext.newInstance(Test.class);
      		Marshaller m = jc.createMarshaller();
      		SchemaFactory sf = SchemaFactory
      				.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
      		Schema schema = sf.newSchema(new File("test.xsd"));
      		m.setSchema(schema);
      		m.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "test.xsd");
      		m.setEventHandler(new ValidationEventHandler() {
      
      			@Override
      			public boolean handleEvent(ValidationEvent event) {
      				System.out.println("Validaten event received.");
      				return false;
      			}
      		});
      		m.marshal(t, new File("test.xml"));
      
      	}
      
      }
      

      The invocation of Main.main does the following:

      • No exception is raised.
      • The handleEvent-method is not called.
      • A file "test.xml" is written, in which the element "test" carries the attribute "id" twice. Once with value "5", and once with value "10". Hence, it is not well-formed XML.

      Since the operation silently succeeds, a user expects a valid XML with respect to the XML schema. As far as I know, validity w.r.t. schema implies that it is also well-formed. Assuming no schema is used, a user would expect that the output is well-formed if no error or warning is given.

      The ugly workaround is to add an additional check on top of the Marshal validation for well-formedness, as long as this shortcoming exists.

      Side-notes

      I am aware of the fact that this usage of the XmlAnyAttribute-map can be considered as an edge case. Nevertheless, the Marshaller should check for validity of the input. At the moment, the silent-fail-outcome is highly undesirable.

      Proposals

      Proposals in which direction a fix could go:

      1. A Marshaller raises an exception if the output would not be well-formed XML. The postcondition, that the output is always well-formed, should be included in the javadocs.
        1. In the special case where a regularly mapped attribute is again specified in the XmlAnyAttribute-map, this error is explained in the exception.
      2. If proposal 1 can not be implemented: When using a XML schema on a Marshaller, the validation succeeds only if the XML is also well-formed.

      Thanks for looking into this!

        Activity

        Hide
        m4t added a comment -

        A situation where also not well-formed XML is produced, but doesn't build on attribute collision, is the following:

        If you store an attribute with empty name into the QName-map. Replace

        new QName("id")

        with

        new QName("")

        in the above example. No exception is raised, the produced string is not XML (attribute with empty name). I guess also invalid characters for XML would not be intercepted.

        Show
        m4t added a comment - A situation where also not well-formed XML is produced, but doesn't build on attribute collision, is the following: If you store an attribute with empty name into the QName-map. Replace new QName( "id" ) with new QName("") in the above example. No exception is raised, the produced string is not XML (attribute with empty name). I guess also invalid characters for XML would not be intercepted.

          People

          • Assignee:
            Iaroslav Savytskyi
            Reporter:
            m4t
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: