Details
-
Type:
Bug
-
Status:
Reopened
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: 0.9.5.2
-
Fix Version/s: None
-
Component/s: XML code generator
-
Labels:None
-
Environment:Operating System: other
Platform: PC
-
Bugzilla Id:879
-
Number of attachments :2
Description
I use the code generator to create Java value classes from xml schema.
When I derive a complex type by restriction, the redefined/repeated content
illegally appears twice in the marshalled xml.
here's an example:
XML schema:
<complexType name = "MyBaseType"> <attribute name = "name" use = "required" type = "string"/> <attribute name = "someOtherAttr" default = "false" type = "boolean"/> </complexType> <element name = "MyDerivedElement"> <complexType> <complexContent> <restriction base = "MyBaseType"> <attribute name = "name" fixed = "MyConstantName" type = "string"/> <attribute name = "someOtherAttr" default = "false" type = "boolean"/> </restriction> </complexContent> </complexType> </element>
XML output (from marshalling):
<?xml version="1.0"?> <ns1:MyDerivedElement ns1:name="MyConstantName" ns1:someOtherAttr="true" ns1:name="MyConstantName" ns1:someOtherAttr="true" xmlns:ns1="http://mySchemaUrl"/>
– problem details -------------------
First the ctor of MyBaseTypeDescriptor adds all its attributes using
XMLClassDescriptorImpl#addFieldDescriptor, then the ctor of
MyDerivedElementDescriptor does the same again, so that getAttributeDescriptors
() yields everything twice, resulting in an invalid xml doc.
I believe that with restriction of complexTypes, the supertype class should not
add any attribute at all, so that only those attributes are available which are
repeated in the derived class, possibly restricted.
– fix? -------------------
What do you think of having a "clearFieldDescriptors" method in
XMLClassDescriptorImpl? The source generator could insert a call to that method
in the ctor of MyDerivedElementDescriptor.
If you approve to my suggestion or outline some more elegant way to fix the
problem, I'd volunteer to contribute a bugfix.
Thank you very much for your reply!
Cheers, Heiko
-
Hide
- DuplAttr.zip
- 21/Oct/11 11:34 AM
- 2.83 MB
- Alex Milanovic
-
- DuplAttr/bin/compile.bat 0.6 kB
- DuplAttr/bin/cp.jar 0.4 kB
- DuplAttr/bin/makecp.bat 0.2 kB
- DuplAttr/bin/marshal.bat 0.1 kB
- DuplAttr/bin/srcGen.bat 0.6 kB
- DuplAttr/conf/bindingFile.xml 0.5 kB
- DuplAttr/conf/bindingFileNs2.xml 0.6 kB
- DuplAttr/conf/castorbuilder.properties 3 kB
- DuplAttr/conf/log4j.xml 0.9 kB
- DuplAttr/lib/castor-codegen-1.3.2.jar 499 kB
- DuplAttr/lib/castor-core-1.3.2.jar 55 kB
- DuplAttr/lib/castor-xml-1.3.2.jar 828 kB
- DuplAttr/lib/castor-xml-schema-1.3.2.jar 345 kB
- DuplAttr/lib/commons-lang-2.1.jar 203 kB
- DuplAttr/lib/commons-logging-1.1.1.jar 59 kB
- DuplAttr/lib/xercesImpl-2.9.1.jar 1.17 MB
- DuplAttr/src/java/Test.java 0.5 kB
- DuplAttr/src/xml/Attributes.xsd 0.5 kB
- DuplAttr/.../NoMoreDuplicateAttributes.xsd 2 kB
- DuplAttr/.../NoMoreDuplicateAttributesNs2.xsd 0.9 kB
-
- duplicate-attributes.diff
- 26/Dec/06 9:25 PM
- 9 kB
- Edward Kuns
Issue Links
- is related to
-
CASTOR-1606
For a ComplexType derived by restriction, only the validation from the superclass is done.
-
Activity
The bug can be reproduced by defining the base type in a schema A and importing
that schema A in a schema B and then extend the base type.
A solution is to create a class info for each imported types and simply not
output them.
This bug is still alive. I have two schema files:
Header.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?> <schema targetNamespace="http://ns1" xmlns:ns1="http://ns1" xmlns="http://www.w3.org/2001/XMLSchema"> <complexType name="Header"> <attribute name="type" type="string" use="required"/> </complexType> </schema>
SpecialHeader.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?> <schema targetNamespace="http://ns2" xmlns:ns2="http://ns2" xmlns:ns1="http://ns1" xmlns="http://www.w3.org/2001/XMLSchema"> <import namespace="http://ns1" schemaLocation="Header.xsd"/> <element name="SpecialHeader"> <complexType> <complexContent> <restriction base="ns1:Header"> <attribute name="type" type="string" use="required" fixed="SPECIAL"/> </restriction> </complexContent> </complexType> </element> </schema>
I have two problems with this. One (minor, but annoying) thing is that in
SpecialHeader.java Castor generates sv.setFixed(), and unfortunately the name of the method
in StringValidator is setFixedValue(). And after correcting this manually, the result of
marshalling is:
<?xml version="1.0"?>
<SpecialHeader type="SPECIAL" type="SPECIAL"
xmlns="http://ns2"/>
I have used the 0.9.3.21 build.
I face the following problem when un-marshalling an instance XML document.
I have an element 'foo' with anonymous complexType, which restricts a base
complexType 'FooType'. The anonymous complexType has fewer elements than the
base complexType.
The generated code for 'foo' element in Foo.java directly extends the base
complextType FooType in FooType.java instead of the corresponding class for
anonymous type. Also, no class was generated for the anonymous complexType.
As a result, when un-marshalling the XML document, I get a ValidationException
saying that the elements in FooType are required though they can be omitted in
the instance XML as per the restriction on the 'foo' element.
I used the 'type' for defaultBindingType attribute in the binding XML.
I think the other side of the same issue.
Thank you for your help.
Michael, you shouldn't change the target milestone, unless you are willing to do
the work on fixing the bug for that release.
You may change the version number affected, but the target milestone should only
be set by the person who will do the work to make sure the bug will be fixed by
that milestone.
Was that your intention?
I have a similar issue with version 0.9.7
I patched the DocumentHandlerAdapter.java class to fix it for my situation (i called marshaller.setSuppressNamespaces(true)):
Current code in 0.9.7:
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException
{
AttributeListImpl attList = new AttributeListImpl();
//-- Create a new namespace scope if necessary and
//-- make sure the flag is reset to true
if (_createNamespaceScope) {
//-- no current namespaces, but we create a new scope
//-- to make things easier in the endElement method
_namespaces = _namespaces.createNamespaces();
}
else {
_createNamespaceScope = true;
_namespaces.declareAsAttributes(attList, true);
}
//-- copy Attributes to AttributeList
for (int i = 0; i < atts.getLength(); i++) {
attList.addAttribute(atts.getQName(i), CDATA, atts.getValue(i));
}
_handler.startElement(qName, attList);
}
New patched code that fixes the issue for me:
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException
{
AttributeListImpl attList = new AttributeListImpl();
//-- Create a new namespace scope if necessary and
//-- make sure the flag is reset to true
if (_createNamespaceScope) {
//-- no current namespaces, but we create a new scope
//-- to make things easier in the endElement method
_namespaces = _namespaces.createNamespaces();
}
else {
_createNamespaceScope = true;
_namespaces.declareAsAttributes(attList, true);
}
//-- copy Attributes to AttributeList
Set checkDuplSet = new HashSet();
for (int i = 0; i < atts.getLength(); i++) {
final String qname = atts.getQName(i);
if (!checkDuplSet.contains(qname))
{
attList.addAttribute(qname, CDATA, atts.getValue(i));
checkDuplSet.add(qname);
}
}
checkDuplSet.clear(); checkDuplSet = null;
_handler.startElement(qName, attList);
}
The difference is in the use of the Set 'checkDuplSet', used to check if an attribute is about to be added more than once.
Maybe this helps in fixing this bug.
Since the Marshaller calls this method, the real fix should be done in Marshaller.java?
Sincerely,
– Anton Spaans.
Attaching a diff of the proposed fix above. I ran into this problem investigating a different problem, but the resolution to that Jira issue may affect whether or not this fix should be delivered anywhere or whether the other issue I'm looking into will fix this one also.
Now, looking at the patch attached above, I'd love to be able to run a test case that allows me to replay this issue.
This problem affects my work too with Castor 1.3.2. If you look at the Geography Markup Language (GML) schemas, specifically at http://schemas.opengis.net/gml/3.1.1/base/gmlBase.xsd, there is an attribute group called AssociationAttributeGroup defined as:
<attributeGroup name="AssociationAttributeGroup"> <attributeGroup ref="xlink:simpleLink"/> <attribute ref="gml:remoteSchema" use="optional"/> </attributeGroup>
Now, derivation by restriction is used often in GML (along with the substitution groups) and this attribute group is declared first in a base type and then re-declared in subtypes. This is necessary so that the attributes would be present in each subtype. Not surprisingly, Castor Source Generator generates these attributes on both the base type and the subtype. This in itself is not a problem though. The problem occurs upon marshalling when the Marshaller erroneously marshals the values from the subtype twice. So if TypeB restricts TypeA, and only TypeB actually has any values specified in the AssociationAttributeGroup attributes the Marshaller will marshal these values twice thereby creating invalid XML content.
Alex, can I please ask you to supply me with a minimal XML schema and a unit tst that allows me to reply the problem ? Thanks in advance.
This self-contained example (only JAVA_HOME must be set) shows that marshalling produces duplicate attributes and even elements in the case of derivation by restriction. Under the bin folder execute the following batch files: srcGen.bat, compile.bat and marshal.bat, in the same order. The last batch file (marshal) will print out the XML content with duplicate attributes and elements. I tried to make the example schemas as compact as possible but it turns out that this problem does not happen with simple cases. In this cases, we have three schema files under src/xsd, each with its own namespace. While this combination may look outlandish it actually occurs in an ISO standard Geography Markup Language and therefore is not something that one designs just to break Castor
.
This is the output of the marshal.bat program. Attributes ns1:href and ns1:type are outputted twice, which is the original reason for my posting (except that in the real-world case it is the xlink:href and xlink:type). In addition, the element elem1 was printed out twice albeit with different prefixes (the namespace is identical though).
<derivedElemNs2 xmlns="http://no-more-duplicate-attributes-ns2.com" xmlns:ns1="http://attributes.com" ns1:href="#323" ns1:type="simple" ns1:href="#323" ns1:type="simple"> <ns2:elem1 xmlns:ns2="http://no-more-duplicate-attributes.com">Ick bin ein Berliner</ns2:elem1> <ns3:elem1 xmlns:ns3="http://no-more-duplicate-attribut es.com">Ick bin ein Berliner</ns3:elem1> </derivedElemNs2>
This is necessary so that the attributes would be present in each subtype.
For my own education, why would that actually be necessary ?
In derivation-by-restriction the content model of the base type is not automatically inherited as is the case with derivation-by-extension. One has to declare each part of the base type that one wants to inherit and potentially restrict. If one omits the attribute group in the subtype it is like saying that maxOccurs="0", i.e. those attributes don't exist in the restricted subtype and they can't be used in the elements of that subtype. It is how XML Schema works. Unfortunately, that's now how inheritance in Java works so it might not be straightforward to model this in Java.
Regarding Castor, I think it's Ok if the re-declared attributes appear as class members on both the base type and the derived type. However, the Marshalling framework should not marshal the same attribute (or element) more than once.
Hello,
Any news on this issue ?
I am still getting duplicated attributes when marshalling in the same use case described by Alex.
For info, I am using the latest version of the castor maven plugin (v 2.1).
Is there any Castor option that can control this marshalling behavior ?
Regards,
Mark
Hi Heiko,
Thanks for reporting the bug and your interest in helping get it fixed...
I think the correct approach is to check the derivation method of the
complexType before creating the ClassInfo. If the derivation method is
restriction, then logic should be added to process the restriction properly. For
example, polymorhpic methods should be added that override the base classes
methods to say something is not supported, or violates the new restriction.
The logic in the generated descriptors should be extended such that only the
proper FieldDescriptors are returned so that any necessary validation can occur
for the restriction of the field.
I'm assigning this to Arnaud as he is the author of the original restriction
code.