CDATA appearing in xsd:any data [message #1385978] |
Thu, 12 June 2014 11:09  |
Eclipse User |
|
|
|
Hi Ed,
I have stumbled accross something a little strange that I would really appreciate your input on.
I have a schema as follows:
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
<xs:any processContents="lax" minOccurs="0" maxOccurs="5" ecore:name="customAny"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Then if I do something like:
Car createCar = ElmAndComplexFactory.eINSTANCE.createCar();
createCar.setColour("red");
// Now create the Complex object with the any
personType createpersonType = SimpleAnyNamedFactory.eINSTANCE.createpersonType();
createpersonType.setFirstname("Betty");
createpersonType.setLastname("Rubble");
createpersonType.setCustomAny(createCar);
String s = serialize(createpersonType);
// Remove from the package reg for the value we are putting into the xsd:any
// Need to first save off the entry - we will add it later
String regKey = ElmAndComplexFactory.eINSTANCE.getEPackage().getNsURI();
OSGiEnabledPackageRegistry.INSTANCE.remove(regKey);
personType personType2 = (personType) deserialize(s);
s = serialize(personType2);
System.out.println(s);
It's a bit contrived in this example - our case is a bit more complicated, the key bit is once we have it in an XML format we then make sure the type in the "xsd:any" is no longer in the EMF Registry. The serialise/deserialise methods just do a save/load on the resource. When sysout is done it will print:
<named:person xmlns:ElmAndComplex="http://example.com/ElmAndComplex" xmlns:named="http://example.com/SimpleAnyNamed">
<firstname>Betty</firstname>
<lastname>Rubble</lastname>
<ElmAndComplex:myCarElement>
<colour>red</colour>
</ElmAndComplex:myCarElement>
</named:person>
This is all good, but if we now set the following option to "true":
XMLResource.OPTION_ESCAPE_USING_CDATA
Then we get the following XML:
<named:person xmlns:ElmAndComplex="http://example.com/ElmAndComplex" xmlns:named="http://example.com/SimpleAnyNamed">
<firstname>Betty</firstname>
<lastname>Rubble</lastname>
<ElmAndComplex:myCarElement><![CDATA[
]]><colour>red</colour><![CDATA[
]]></ElmAndComplex:myCarElement>
</named:person>
The problem is "<![CDATA[" values which appear where there is any white space in the XML - it is a bit like it is treating the xsd:any as a string, and hence escaping it.
Any thoughts you have would be appreciated.
Thanks
Rob
|
|
|
|
Re: CDATA appearing in xsd:any data [message #1386079 is a reply to message #1386031] |
Fri, 13 June 2014 07:14  |
Eclipse User |
|
|
|
OK, I have looked a little further into this, it appears that whenever data is stored into an "xsd:any" it assumes that it is "mixed xml" - this means that it always believes that it should print it exactly as the input data. When mixed isn't supported for the XML added to the xsd:any, then this isn't normally a problem as it would just be white space - which will be ignored within the generated XML.
However, when you set EMF to add CDATA to everything - then it will detect this white-space between elements - and add a CDATA around it. (Which may not be valid if the original schema for the object stored into the xsd:any did not support mixed)
I have managed to work around this by editing XMLSaveImpl in the method saveElementFeatureMap, so that in the if for "MLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__TEXT" we now have:
if (entryFeature == XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__TEXT)
{
String svalue = value.toString();
if (escape != null)
{
boolean convertTxt = true;
// CHANGE START
// This could be done in a single line, but it is quite hard to
// work out the rules when viewed this way, so I have split it
// into several lines
if (usingCData)
{
if ((o instanceof AnyType) && (f instanceof EAttribute))
{
if (svalue.trim().length() == 0)
{
convertTxt = false;
}
}
}
// CHANGE END
if( convertTxt )
{
svalue = escape.convertText(svalue);
}
}
if (!toDOM)
{
doc.addText(svalue);
}
else
{
Node text = document.createTextNode(svalue);
currentNode.appendChild(text);
handler.recordValues(text, o, f, entry);
}
}
The "usingCData" variable is the value read out of the passed in options to "init".
|
|
|
Powered by
FUDForum. Page generated in 0.04384 seconds