castor

ExtraElement not ignored in UnmarshalHandler.startElement although it should be ignored

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 0.9.5.2
  • Fix Version/s: 0.9.9 M2
  • Component/s: XML
  • Labels:
    None
  • Environment:
    Operating System: other
    Platform: Other
  • Number of attachments :
    1

Description

Although the unmarshaller is configured with "unm.setIgnoreExtraElements( true )" the
UnmarshalHandler does not ignore a nested unknown tag which has the same name like a known tag
within a container two level higher.

i.e.:

<root>
<container1>
<culpritTag> <--
this is known by the schema
</culpritTag>
<container2>
<culpritTag> <-- this is NOT known by
the schema and should be ignored
...
</culpritTag>
</container2>

</container1>
</root>

The bug is located in the (private)
UnmarshalHandler.startElement method.

part of this method (my comments marked with
>>>>>HB<<<<<:

...

//-- loop through stack and find correct descriptor
int pIdx =
_stateInfo.size() - 2; //-- index of parentState
UnmarshalState targetState = parentState;

String path = "";
StringBuffer pathBuf = null;
int count = 0;
boolean isWrapper = false;

XMLClassDescriptor oldClassDesc = classDesc;
while (descriptor == null) {

descriptor =
classDesc.getFieldDescriptor(name, NodeType.Element);

>>>>>HB<<<<<: within the
third loop the descriptor is no more NULL since it has found the "culpritTag" in container1

//--
Namespace patch, should be moved to XMLClassDescriptor, but
//-- this is the least intrusive
patch at the moment. kv - 20030423
if ((descriptor != null) && (!descriptor.isContainer()))
{
if ((namespace != null) && (namespace.length() > 0)) {
if (!namespaceEquals(namespace,
descriptor.getNameSpaceURI())) {
//-- if descriptor namespace is not null, then we must
//--
have a namespace match, so set descriptor to null,
//-- or if descriptor is not a wildcard we can
also
//-- set to null.
if ((descriptor.getNameSpaceURI() != null) ||
(!descriptor.matches("*"))) { descriptor = null; }

}
}
}
//-- end namespace
patch

/*
If descriptor is null, we need to handle possible inheritence,
which might
not be described in the current ClassDescriptor.
This can be a slow process...for speed use the
match attribute
of the xml element in the mapping file. This logic might
not be completely
necessary, and perhaps we should remove it.
*/
if ((descriptor == null) && (count == 0) &&
(!targetState.wrapper)) {
MarshalFramework.InheritanceMatch[] matches =
searchInheritance(name, namespace, classDesc, _cdResolver);
if (matches.length != 0) { InheritanceMatch match = matches[0]; descriptor = match.parentFieldDesc; cdInherited = match.inheritedClassDesc; break; //-- found }
isWrapper = (isWrapper ||
hasFieldsAtLocation(name, classDesc));
}
else if (descriptor != null) { >>>>>HB<<<<<: Flow is then entering here String tmpPath = descriptor.getLocationPath(); if (tmpPath == null) tmpPath = ""; if (path.equals(tmpPath)) break; //-- found >>>>>HB<<<<<: This if returns false, so no break occurs, but the variable "descriptor" is still assigned so it breaks when it tries to enter the loop again. You should put an else part where the "descriptor" is set to NULL again. }
else { if (pathBuf == null) pathBuf = new StringBuffer(); else pathBuf.setLength(0); pathBuf.append(path); pathBuf.append('/'); pathBuf.append(name); isWrapper = (isWrapper || hasFieldsAtLocation(pathBuf.toString(), classDesc)); }

//-- Make sure there are more
parent classes on stack
//-- otherwise break, since there is nothing to do
if (pIdx == 0)
break;

//-- adjust name and try parent
if (count == 0)
path = targetState.elementName;

else { if (pathBuf == null) pathBuf = new StringBuffer(); else pathBuf.setLength(0); pathBuf.append(targetState.elementName); pathBuf.append('/'); pathBuf.append(path); path = pathBuf.toString(); }

//-- get

--pIdx;
targetState = (UnmarshalState)_stateInfo.elementAt(pIdx);
classDesc =
targetState.classDesc;
count++;
}

//-- The field descriptor is still null, we face a
problem
if (descriptor == null) {
>>>>>HB<<<<<: This if is not entered since descriptor is
not NULL. But it should be entered !
//-- reset classDesc
classDesc = oldClassDesc;

//--
isWrapper?
if (isWrapper) {
state.classDesc = new
XMLClassDescriptorImpl(ContainerElement.class, name);
state.wrapper = true;
if
(debug) { message("wrapper-element: " + name); }
//-- process attributes

processWrapperAttributes(atts);
return;
}

String mesg = "unable to find
FieldDescriptor for '" + name;
mesg += "' in ClassDescriptor of " +
classDesc.getXMLName();

//-- unwrap classDesc, if necessary, for the check
//--
Introspector.introspected done below
if (classDesc instanceof
InternalXMLClassDescriptor) { classDesc = ((InternalXMLClassDescriptor)classDesc).getClassDescriptor(); }

//-- If we are
skipping elements that have appeared in the XML but for
//-- which we have no mapping, increase the
ignore depth counter and return
if (! _strictElements) {
++_ignoreElementDepth;
//--
remove the StateInfo we just added
_stateInfo.pop();
if (debug) { message(mesg + " - ignoring extra element."); }
return;
}
//if we have no field descriptor and
//the
class descriptor was introspected
//just log it
else if
(Introspector.introspected(classDesc)) { //if (warn) message(mesg); return; }

//-- otherwise report error since we cannot find a suitable
//-- descriptor
else { throw new SAXException(mesg); }
} //-- end null descriptor

...

Activity

Hide
Keith Visco added a comment -

Hi Heri, can you attach a diff -u so I can the changes easier.

Show
Keith Visco added a comment - Hi Heri, can you attach a diff -u so I can the changes easier.
Hide
Heri Bender added a comment -

Dear Keith

I dont know "diff -u". My remarks within the cited code are clearly marked with
>>>>>HB<<<<< (three locations = two comments + one change proposal), so it
should be no problem for you to locate the problem.

Show
Heri Bender added a comment - Dear Keith I dont know "diff -u". My remarks within the cited code are clearly marked with >>>>>HB<<<<< (three locations = two comments + one change proposal), so it should be no problem for you to locate the problem.
Hide
Nikolai V. Chr. added a comment -

Has this issue been solved?
Especially the part that goes like this:

//-- Namespace patch, should be moved to XMLClassDescriptor, but
//-- this is the least intrusive patch at the moment. kv - 20030423

[...]

//-- end namespace patch

Show
Nikolai V. Chr. added a comment - Has this issue been solved? Especially the part that goes like this: //-- Namespace patch, should be moved to XMLClassDescriptor, but //-- this is the least intrusive patch at the moment. kv - 20030423 [...] //-- end namespace patch
Hide
Heri Bender added a comment -

My bug description has nothing to do with the namespace problem.

I marked my comments and suggestions with >>>>>HB<<<<<. Isn't it obvious? I
can't believe such a simple bug fix lasts that long!

Show
Heri Bender added a comment - My bug description has nothing to do with the namespace problem. I marked my comments and suggestions with >>>>>HB<<<<<. Isn't it obvious? I can't believe such a simple bug fix lasts that long!
Hide
Cedric Bompart added a comment -

This example captures this issue.

If you comment in line 58 to 60 (TestCastor class) then you should get an exception.

Here is the input XML:

<Response>
<Dob>01012005</Dob>
<User>
<Name>Cedric</Name>
<Title>M</Title>
<Dob>28011976</Dob>
</User>
</Response>

Here is a working mapping file, both "Dob" elements are not mapped.

<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<class cst:name="castor.Response">
<map-to cst:xml="Response" />
<field cst:name="user" cst:type="castor.User" cst:collection="array">
<bind-xml name="User" node="element" />
</field>
</class>

<class cst:name="castor.User">
<map-to cst:xml="User" />
<field cst:name="name" cst:type="java.lang.String">
<bind-xml name="Name" node="element" />
</field>
<field cst:name="title" cst:type="java.lang.String">
<bind-xml name="Title" node="element" />
</field>
</class>
</mapping>

If you add a mapping for the first "Dob":

<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<class cst:name="castor.Response">
<map-to cst:xml="Response" />
<field cst:name="user" cst:type="castor.User" cst:collection="array">
<bind-xml name="User" node="element" />
</field>
<field cst:name="dob" cst:type="java.lang.String">
<bind-xml name="Dob" node="element" />
</field>
</class>

<class cst:name="castor.User">
<map-to cst:xml="User" />
<field cst:name="name" cst:type="java.lang.String">
<bind-xml name="Name" node="element" />
</field>
<field cst:name="title" cst:type="java.lang.String">
<bind-xml name="Title" node="element" />
</field>
</class>
</mapping>

then you get an exception against the "User" structure for its "Dob" element.

additionally if you comment out line 40 (which is the Dob from the user structure) then you should get a working example.

So it looks like there is an "issue" with the mapping logic around duplicate elements in different structure in the same class mapping.

Show
Cedric Bompart added a comment - This example captures this issue. If you comment in line 58 to 60 (TestCastor class) then you should get an exception. Here is the input XML: <Response> <Dob>01012005</Dob> <User> <Name>Cedric</Name> <Title>M</Title> <Dob>28011976</Dob> </User> </Response> Here is a working mapping file, both "Dob" elements are not mapped. <?xml version="1.0" encoding="UTF-8"?> <mapping> <class cst:name="castor.Response"> <map-to cst:xml="Response" /> <field cst:name="user" cst:type="castor.User" cst:collection="array"> <bind-xml name="User" node="element" /> </field> </class> <class cst:name="castor.User"> <map-to cst:xml="User" /> <field cst:name="name" cst:type="java.lang.String"> <bind-xml name="Name" node="element" /> </field> <field cst:name="title" cst:type="java.lang.String"> <bind-xml name="Title" node="element" /> </field> </class> </mapping> If you add a mapping for the first "Dob": <?xml version="1.0" encoding="UTF-8"?> <mapping> <class cst:name="castor.Response"> <map-to cst:xml="Response" /> <field cst:name="user" cst:type="castor.User" cst:collection="array"> <bind-xml name="User" node="element" /> </field> <field cst:name="dob" cst:type="java.lang.String"> <bind-xml name="Dob" node="element" /> </field> </class> <class cst:name="castor.User"> <map-to cst:xml="User" /> <field cst:name="name" cst:type="java.lang.String"> <bind-xml name="Name" node="element" /> </field> <field cst:name="title" cst:type="java.lang.String"> <bind-xml name="Title" node="element" /> </field> </class> </mapping> then you get an exception against the "User" structure for its "Dob" element. additionally if you comment out line 40 (which is the Dob from the user structure) then you should get a working example. So it looks like there is an "issue" with the mapping logic around duplicate elements in different structure in the same class mapping.
Hide
Andrew Fawcett added a comment -

Applied patch sent by Heri Bender. Thanks!

Show
Andrew Fawcett added a comment - Applied patch sent by Heri Bender. Thanks!
Hide
Cedric Bompart added a comment -

thanks a lot! we've going to put our application into production on the 24th of May, a bit lucky...

Show
Cedric Bompart added a comment - thanks a lot! we've going to put our application into production on the 24th of May, a bit lucky...
Hide
Werner Guttmann added a comment -

Hi, as explained in CASTOR-1174, it looks like the resolution of this bug as committed by Andrew back in May unfortunately causes other code to break. As such, I am currently debating with my later ego whether to back this issue out or not. I do acknowledge that this will not please quite some folks as it will take away a solution for this very problem, but it looks like the patch in question in a bit incomplete and causes quite severe problems with more sophisticated 'locations'. Well, let's hear your views first ...

Show
Werner Guttmann added a comment - Hi, as explained in CASTOR-1174, it looks like the resolution of this bug as committed by Andrew back in May unfortunately causes other code to break. As such, I am currently debating with my later ego whether to back this issue out or not. I do acknowledge that this will not please quite some folks as it will take away a solution for this very problem, but it looks like the patch in question in a bit incomplete and causes quite severe problems with more sophisticated 'locations'. Well, let's hear your views first ...
Hide
Werner Guttmann added a comment -

As explained above ...

Show
Werner Guttmann added a comment - As explained above ...
Hide
Gregory Block added a comment -

Dependent bug closed; the patch remains in place. Re-closing this bug.

Show
Gregory Block added a comment - Dependent bug closed; the patch remains in place. Re-closing this bug.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: