Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Attributes in the default namespace?
Attributes in the default namespace? [message #1229172] Wed, 08 January 2014 21:37 Go to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
I have two XSD documents that together describe a LoginRequest class and a LoginResponse class. There is also a WSDL but that is not relevant to the RESTful service. I have used CXF's wsdl2java.bat to generate my JAXB-annotated Java classes.

As long as I use a namespace prefix, everything works fine. I can both marshal and unmarshal JSON representations of my objects. When I assign the namespace prefix to empty string (to specify the default namespace), marshalling still works but on unmarshal a SAX exception is thrown when parsing attributes:
org.xml.sax.SAXParseException; cvc-complex-type.3.2.2: Attribute 'name' is not allowed to appear in element 'UserCredentials'.


Login.xsd:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns:achilles="http://eclipse.org/schemas/api/achilles/v1.0"
  xmlns:xs="http://eclipse.org/2001/XMLSchema" targetNamespace="http://eclipse.org/schemas/api/achilles/v1.0"
  elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1" id="Achilles2013001A">

  <xs:include schemaLocation="Common.xsd" />

  <xs:element name="LoginRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="UserCredentials" type="achilles:UserCredentials" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="LoginResponse">
    <xs:complexType>
      <xs:complexContent>
        <xs:extension base="achilles:Response">
          <xs:sequence>
            <xs:element name="Result">
              <xs:complexType>
                <xs:attribute name="Success" type="xs:boolean" use="required" />
                <xs:attribute name="Token" type="xs:string" />
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>
</xs:schema>


Common.xsd:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns:achilles="http://eclipse.org/schemas/api/achilles/v1.0" xmlns:xs="http://eclipse.org/2001/XMLSchema" targetNamespace="http://eclipse.org/schemas/api/achilles/v1.0" elementFormDefault="qualified" version="1.1" id="Achilles2013001A">
	<xs:element name="UserCredentials" type="achilles:UserCredentials"/>
	<xs:complexType name="UserCredentials">
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="password" type="xs:string"/>
	</xs:complexType>
	<xs:complexType name="Error">
		<xs:simpleContent>
			<xs:extension base="xs:string">
				<xs:attribute name="Type" type="xs:string">
				</xs:attribute>
				<xs:attribute name="Code" type="xs:string">
				</xs:attribute>
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>
	<xs:complexType name="Errors">
		<xs:sequence>
			<xs:element name="Error" type="achilles:Error" maxOccurs="unbounded"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="Response">
		<xs:sequence>
			<xs:element name="Errors" type="achilles:Errors" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
</xs:schema>


JSON with namespace prefix (working):
{"achilles.LoginRequest":{"achilles.UserCredentials":{"@name":"username","@password":"password"}}}


JSON without namespace prefix (marshals only):
{"LoginRequest":{"UserCredentials":{"@name":"username","@password":"password"}}}


Am I doing something wrong? How can I use attributes and a default namespace together?
Re: Attributes in the default namespace? [message #1229949 is a reply to message #1229172] Fri, 10 January 2014 16:22 Go to previous messageGo to next message
Blaise Doughan is currently offline Blaise DoughanFriend
Messages: 163
Registered: July 2009
Senior Member

Hi Nate,

Here is what I did to get your example to work:

XML Schemas

I changed the xmlns:xs declaration to be the namespace http://www.w3.org/2001/XMLSchema instead of http://eclipse.org/2001/XMLSchema.


Generated a JAXB Model

I generated a JAXB model from the Login.xsd using the all the defaults:

xjc Login.xsd


Demo Code

Here is some code to read/write the JSON:

package org.eclipse.schemas.api.achilles.v1;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

	public static void main(String[] args) throws Exception {
		Map<String, Object> properties = new HashMap<String, Object>(2);
		properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
		properties.put(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX, "@");
		JAXBContext jc = JAXBContext.newInstance("org.eclipse.schemas.api.achilles.v1", ObjectFactory.class.getClassLoader(), properties);
		
		Unmarshaller unmarshaller = jc.createUnmarshaller();
		File json = new File("src/org/eclipse/schemas/api/achilles/v1/input.json");
		LoginRequest loginRequest = (LoginRequest) unmarshaller.unmarshal(json);
		
		Marshaller marshaller = jc.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		marshaller.marshal(loginRequest, System.out);
	}

}


Input/Output

Here is the JSON document I used for this example:
{
   "LoginRequest" : {
      "UserCredentials" : {
         "@name" : "username",
         "@password" : "password"
      }
   }
}


-Blaise
Re: Attributes in the default namespace? [message #1230009 is a reply to message #1229949] Fri, 10 January 2014 19:45 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
Thanks, Blaise. It seems I left out a crucial detail, however: I have schema validation enabled and the exception that I'm seeing stems from
com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl


First, I load my XSDs:
private Schema getSchema(final String schemaPath, final String[] schemaNames) throws SAXException
{
	final SchemaFactory sf = new XMLSchemaFactory();
	sf.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE, true);
	sf.setProperty(XMLSchemaLoader.ENTITY_RESOLVER, new XMLEntityResolver()
	{
		@Override
		public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
				throws XNIException, IOException
		{
			return new XMLInputSource(null, resourceIdentifier.getLiteralSystemId(), resourceIdentifier
					.getLiteralSystemId(), getClass().getResourceAsStream(
					schemaPath + "/" + resourceIdentifier.getLiteralSystemId()), null);
		}
	});

	final StreamSource[] sources = new StreamSource[schemaNames.length];
	for (int i = 0; i < schemaNames.length; i++)
		sources[i] = new StreamSource(getClass().getResourceAsStream(
				schemaPath + "/" + schemaNames[i]), schemaNames[i]);

	return sf.newSchema(sources);
}


And then I set the schema and namespace map on my Unmarshaller:
unmarshaller.setSchema(schema);
unmarshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespaceMap)


The namespace map includes an entry mapping from the namespace
"http://eclipse.org/schemas/api/achilles/v1.0"
to the prefix
""


And then when I unmarshal a document with an empty namespace prefix (as in my OP), an exception is thrown from the XMLSchemaValidator:
Caused by: org.xml.sax.SAXParseException; cvc-complex-type.3.2.2: Attribute 'name' is not allowed to appear in element 'UserCredentials'.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:453)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3232)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processAttributes(XMLSchemaValidator.java:2709)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2051)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:741)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.startElement(ValidatorHandlerImpl.java:565)
	at org.eclipse.persistence.internal.oxm.record.XMLReader$ValidatingContentHandler.startElement(XMLReader.java:431)
	at org.eclipse.persistence.internal.oxm.record.XMLReaderAdapter$ExtendedContentHandlerAdapter.startElement(XMLReaderAdapter.java:178)
	at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:302)
	at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:436)
	at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:303)
	at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:166)
	at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:125)
	at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:972)
	... 46 more
Re: Attributes in the default namespace? [message #1230107 is a reply to message #1230009] Sat, 11 January 2014 01:49 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
The W3C URL is incorrect in the XML documents due to a constraint of this forum combined with my low post count.
Re: Attributes in the default namespace? [message #1230109 is a reply to message #1230107] Sat, 11 January 2014 01:50 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
Another developer on my team has discovered that this problem is related to declaring attributeFormDefault=\"qualified\", however the XML and JSON serializers behave in opposite ways.
Re: Attributes in the default namespace? [message #1230110 is a reply to message #1230109] Sat, 11 January 2014 01:51 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
Here is the output:
xml (prefixed:qualified) passed
xml (prefixed:unqualified) failed
xml (default:qualified) failed
xml (default:unqualified) passed
json (prefixed:qualified) failed
json (prefixed:unqualified) passed
json (default:qualified) passed
json (default:unqualified) failed


So what this is saying is that when unmarshalling JSON, if there is a default namespace and the attributeFormDefault="qualified", then there is no error. In this case, however, XML unmarshalling will fail. Basically it seems like XML and JSON are handled inconsistently in this case.

[Updated on: Sat, 11 January 2014 01:56]

Report message to a moderator

Re: Attributes in the default namespace? [message #1230111 is a reply to message #1230110] Sat, 11 January 2014 01:52 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
Here is the code producing the above output:
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;

import com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory;

public class MoxyTest5
{
	@XmlRootElement(name = "CatalogRequest", namespace = "http://ws.cyllenius.com/schemas/api/platform/v1.0")
	@XmlAccessorType(XmlAccessType.FIELD)
	public static class CatalogRequest
	{
		@XmlAttribute(name = "IncludeContent")
		protected Boolean includeContent;

		public boolean isIncludeContent()
		{
			if (includeContent == null)
				return true;
			else
				return includeContent;
		}

		public void setIncludeContent(boolean value)
		{
			this.includeContent = value;
		}

		public boolean isSetIncludeContent()
		{
			return (this.includeContent != null);
		}

		public void unsetIncludeContent()
		{
			this.includeContent = null;
		}
	}

	private static final String schemaWithAttributesQualified = "" //
			+ "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>" //
			+ "<xs:schema xmlns:cyllenius=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"qualified\" id=\"Cyllenius2010001A\" targetNamespace=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" version=\"1.1\">" //
			+ "  <xs:element name=\"CatalogRequest\" type=\"cyllenius:CatalogRequest\"/>" //
			+ "  <xs:complexType name=\"CatalogRequest\">" //
			+ "    <xs:attribute default=\"true\" name=\"IncludeContent\" type=\"xs:boolean\" use=\"optional\">" //
			+ "    </xs:attribute>" //
			+ "  </xs:complexType>" //
			+ "</xs:schema>";
	private static final String schemaWithoutAttributesQualified = "" //
			+ "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>" //
			+ "<xs:schema xmlns:cyllenius=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" id=\"Cyllenius2010001A\" targetNamespace=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" version=\"1.1\">" //
			+ "  <xs:element name=\"CatalogRequest\" type=\"cyllenius:CatalogRequest\"/>" //
			+ "  <xs:complexType name=\"CatalogRequest\">" //
			+ "    <xs:attribute default=\"true\" name=\"IncludeContent\" type=\"xs:boolean\" use=\"optional\">" //
			+ "    </xs:attribute>" //
			+ "  </xs:complexType>" //
			+ "</xs:schema>";

	private static CatalogRequest parseJSON(final Map<String, String> namespaceMap,
			final String json, final String schemaString) throws Exception
	{
		final JAXBContext context = JAXBContextFactory.createContext(
				new Class[] { CatalogRequest.class }, new HashMap<String, String>());

		final Unmarshaller unmarshaller = context.createUnmarshaller();
		unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
		unmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX, "@");
		unmarshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespaceMap);

		final Schema schema = new XMLSchemaFactory().newSchema(new StreamSource(new StringReader(
				schemaString)));
		unmarshaller.setSchema(schema);

		return (CatalogRequest) unmarshaller.unmarshal(new StringReader(json));
	}

	private static CatalogRequest parseXML(final String xml, final String schemaString)
			throws Exception
	{
		final JAXBContext context = JAXBContextFactory.createContext(
				new Class[] { CatalogRequest.class }, new HashMap<String, String>());

		final Unmarshaller unmarshaller = context.createUnmarshaller();
		unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_XML);

		final Schema schema = new XMLSchemaFactory().newSchema(new StreamSource(new StringReader(
				schemaString)));
		unmarshaller.setSchema(schema);

		return (CatalogRequest) unmarshaller.unmarshal(new StringReader(xml));
	}

	public static void main(final String[] argv)
	{
		try
		{
			final String xml = "<cyllenius:CatalogRequest xmlns:cyllenius=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" cyllenius:IncludeContent=\"true\" />";

			parseXML(xml, schemaWithAttributesQualified);
			System.out.println("xml (prefixed:qualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("xml (prefixed:qualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final String xml = "<cyllenius:CatalogRequest xmlns:cyllenius=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" cyllenius:IncludeContent=\"true\" />";

			parseXML(xml, schemaWithoutAttributesQualified);
			System.out.println("xml (prefixed:unqualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("xml (prefixed:unqualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final String xml = "<CatalogRequest xmlns=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" IncludeContent=\"true\" />";

			parseXML(xml, schemaWithAttributesQualified);
			System.out.println("xml (default:qualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("xml (default:qualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final String xml = "<CatalogRequest xmlns=\"http://ws.cyllenius.com/schemas/api/platform/v1.0\" IncludeContent=\"true\" />";

			parseXML(xml, schemaWithoutAttributesQualified);
			System.out.println("xml (default:unqualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("xml (default:unqualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final Map<String, String> namespaceMap = new HashMap<String, String>();
			namespaceMap.put("http://ws.cyllenius.com/schemas/api/platform/v1.0", "cyllenius");

			final String json = "{\"cyllenius.CatalogRequest\":{\"@IncludeContent\":\"true\"}}";

			parseJSON(namespaceMap, json, schemaWithAttributesQualified);
			System.out.println("json (prefixed:qualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("json (prefixed:qualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final Map<String, String> namespaceMap = new HashMap<String, String>();
			namespaceMap.put("http://ws.cyllenius.com/schemas/api/platform/v1.0", "cyllenius");

			final String json = "{\"cyllenius.CatalogRequest\":{\"@IncludeContent\":\"true\"}}";

			parseJSON(namespaceMap, json, schemaWithoutAttributesQualified);
			System.out.println("json (prefixed:unqualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("json (prefixed:unqualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final Map<String, String> namespaceMap = new HashMap<String, String>();
			namespaceMap.put("http://ws.cyllenius.com/schemas/api/platform/v1.0", "");

			final String json = "{\"CatalogRequest\":{\"@IncludeContent\":\"true\"}}";

			parseJSON(namespaceMap, json, schemaWithAttributesQualified);
			System.out.println("json (default:qualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("json (default:qualified) failed");
			// e.printStackTrace();
		}

		try
		{
			final Map<String, String> namespaceMap = new HashMap<String, String>();
			namespaceMap.put("http://ws.cyllenius.com/schemas/api/platform/v1.0", "");

			final String json = "{\"CatalogRequest\":{\"@IncludeContent\":\"true\"}}";

			parseJSON(namespaceMap, json, schemaWithoutAttributesQualified);
			System.out.println("json (default:unqualified) passed");
		}
		catch (final Exception e)
		{
			System.err.println("json (default:unqualified) failed");
			// e.printStackTrace();
		}
	}
}
Re: Attributes in the default namespace? [message #1237877 is a reply to message #1230111] Thu, 30 January 2014 21:02 Go to previous messageGo to next message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
This seems like an inconsistency with MOXy -- do you think that's the case?
Re: Attributes in the default namespace? [message #1246344 is a reply to message #1237877] Sat, 15 February 2014 00:44 Go to previous message
nate roe is currently offline nate roeFriend
Messages: 8
Registered: January 2014
Junior Member
Bump -- I'd really like to use a default namespace at the same time as schema validation. Is this possible? Is something wrong with my example?
Previous Topic:Query for entity.collection returns List with one element which is null (instead of empty list)
Next Topic:Dynamic: how to configure generated id using API?
Goto Forum:
  


Current Time: Mon Dec 22 08:37:26 GMT 2014

Powered by FUDForum. Page generated in 0.02486 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software