Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 367141

Summary: XMLLib.convertFromXML issue with nested simpleContent records
Product: z_Archived Reporter: Dan Darnell <dan.darnell>
Component: EDTAssignee: Project Inbox <edt.compiler-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: jvincens, smythew, svihovec
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Dan Darnell CLA 2011-12-19 18:16:15 EST
Build Identifier: 

Converting an XML document that contains nested simpleContent type records results in an erroneous result. "Steps to reproduce" contains example.

FYI: This works in RBD.

Reproducible: Always

Steps to Reproduce:
Originally manifested when using a service definition that brought back an XML document (parsed automatically), like this:

interface XMLService
	function callProgram(xmlServiceFormData XMLServiceFormData in) returns(XMLServiceParms)
      {@PostRest{ requestFormat = _FORM, responseFormat = XML}};
end

But can also be reproduced as a call to XMLLib.convertFromXML, as shown below.

Service interface looks like this:
interface XMLService
	function callProgram(xmlServiceFormData XMLServiceFormData in) returns(string)
      {@PostRest{ requestFormat = _FORM, responseFormat = NONE}};
end

Records are defined as:
record XMLServiceParms {@XMLRootElement{name = "pgm"}}
	lib string {@XMLAttribute{}};
	name string {@XMLAttribute{}};
	parms Parm[] {@XMLElement{name = "parm"}}; 
end
record Parm {@XMLValue {kind = XMLStructureKind.simpleContent}}
	by1 string {@XMLAttribute{name = "by"}};
	io string {@XMLAttribute{}};
	data Data {@XMLElement{name = "data"}};
end
record Data {@XMLValue {kind = XMLStructureKind.simpleContent}}
	type1 string {@XMLAttribute{name = "type"}};
	value string;
end

XML document returned from the service call looks like this (this is the content of the string variable "result" in the code example below):
"<?xml version="1.0" encoding="UTF-8"?><pgm lib="DDARNELL" name="MYRPG">
<parm by="ref" io="both">
<data type="40a">Hello Dan</data>
</parm>
</pgm>
"

Code to exemplify the issue:
xMLServiceParms XMLServiceParms? = new XMLServiceParms;
XMLLib.convertFromXML(result, xMLServiceParms);
			
In the parsed records "result.parms[1].data" is "\n\n" and we see no structure of "type1" and "value" within "data".

We get the proper results when we simplify the "Parm" record and remove the XMLValue annotation from it and the attributes.

record XMLServiceParms {@XMLRootElement{name = "pgm"}}
	lib string {@XMLAttribute{}};
	name string {@XMLAttribute{}};
	parms Parm[] {@XMLElement{name = "parm"}}; 
end
record Parm 
	data Data {@XMLElement{name = "data"}};
end
record Data {@XMLValue {kind = XMLStructureKind.simpleContent}}
	type1 string {@XMLAttribute{name = "type"}};
	value string;
end

Now, using a document like this:
"<?xml version="1.0" encoding="UTF-8"?><pgm lib="DDARNELL" name="MYRPG">
<parm>
<data type="40a">Hello Dan</data>
</parm>
</pgm>
"

We get a result from XMLLib.convertFromXML like this:
"result.parms[1].data.type1" = "40a"
"result.parms[1].data.value" = "Hello Dan"
Comment 1 Joseph Vincens CLA 2011-12-20 14:19:03 EST
I want to make sure we fix the correct problem. 
Can you include the xsd that you used to create these records?
My understanding of xsd simpleContent is it must be a restriction or extension, so I would expect to see something like:
	<complexType name="Parm">
		<simpleContent>
			<extension base="tns:data">
		    		<attribute name="by" type="string"></attribute>
		    		<attribute name="io" type="string"></attribute>
			</extension>
		</simpleContent>
	</complexType>
    <complexType name="data">
    	<simpleContent>
	    	<extension base="string">
	    		<attribute name="type" type="string"></attribute>
	    	</extension>
    	</simpleContent>
    </complexType>
This will produce different records than what you have below. With the above Parm will embed(RBD egl record extension) Data. In EDT this has its own set of issues, but would be the correct implementation based on my understanding of an xsd simpleContent.
Comment 2 Joseph Vincens CLA 2011-12-20 16:10:02 EST
I spent a little time reading about the XMLSERVICE you are using. I didn't find a schema, but maybe it's in the install and I can't download it yet. 
You said the following works:
record XMLServiceParms {@XMLRootElement{name = "pgm"}}
    lib string {@XMLAttribute{}};
    name string {@XMLAttribute{}};
    parms Parm[] {@XMLElement{name = "parm"}}; 
end
record Parm
    by1 string {@XMLAttribute{name = "by"}};
    io string {@XMLAttribute{}};
    data Data {@XMLElement{name = "data"}};
end
record Data {@XMLValue {kind = XMLStructureKind.simpleContent}}
    type1 string {@XMLAttribute{name = "type"}};
    value string;
end
Is there something wrong with this syntax?

It makes sense there is a PGM which has parameters. A parameter has a data definition. 
Technically speaking if Parm as a simpleContent, then Parm is a data definition, and that doesn't sound quite right.
Comment 3 Dan Darnell CLA 2011-12-20 18:56:16 EST
(In reply to comment #2)
Hi Joe.

What I found to work yesterday looked like this (removing the XMLValue annotation and the attributes from "Parm"):

record XMLServiceParms {@XMLRootElement{name = "pgm"}}
    lib string {@XMLAttribute{}};
    name string {@XMLAttribute{}};
    parms Parm[] {@XMLElement{name = "parm"}}; 
end
record Parm 
    data Data {@XMLElement{name = "data"}};
end
record Data {@XMLValue {kind = XMLStructureKind.simpleContent}}
    type1 string {@XMLAttribute{name = "type"}};
    value string;
end

But you are correct that this works too:

record XMLServiceParms {@XMLRootElement{name = "pgm"}}
    lib string {@XMLAttribute{}};
    name string {@XMLAttribute{}};
    parms Parm[] {@XMLElement{name = "parm"}}; 
end
record Parm
    by1 string {@XMLAttribute{name = "by"}};
    io string {@XMLAttribute{}};
    data Data {@XMLElement{name = "data"}};
end
record Data {@XMLValue {kind = XMLStructureKind.simpleContent}}
    type1 string {@XMLAttribute{name = "type"}};
    value string;
end

Dropping the XMLValue annotation from "Parm" does make the difference and your explanation for why "Parm" should not be defined as simpleContent makes perfect sense.

I could have sworn that I tried this variation... I did find that I had to do a "clean" on occasion to force changes to take effect but I don't know if that had anything to do with this. I think I just missed it.

I am very, very sorry for wasting your time.

(To answer your question about an xsd for XMLService -- I haven't found one. I used a formatted XML document to create the records.)
Comment 4 Joseph Vincens CLA 2011-12-21 07:55:55 EST
You did not waste my time I learned a little about XMLSERVICE. 

I will switch this defect to a validation defect. 

1. XMLValue cam only be placed on a record or handler.
2. It can have any number of fields, all but 1 must be an XMLAttribute.
3. The 1 that is not an XMLAttribute must be a primitive type or an embed <record>. If the part has no XMLElement field then it must extends another part. Embed is a way to do XML extension.
4. The embedded record or super type must follow the same rules.
Comment 5 Joseph Vincens CLA 2012-03-14 06:46:19 EDT
changed the EGL records to resolve the problem
Comment 6 Lisa Lasher CLA 2012-04-04 22:35:25 EDT
This bug is fixed in the final 0.8 driver.  Please verify the fix, and close the bug.  If you still see a problem, you can reopen the bug with additional information.