Hi,

I have problems marshalling (and also unmarshalling) an element with a
content defined as "any".
Here is the definition of the element in our schema (only the type
description):

        <xs:complexType name="embedded_data_type" mixed="true">
                <xs:complexContent mixed="true">
                        <xs:extension base="xs:anyType"/>
                </xs:complexContent>
        </xs:complexType>

This element is used to embedd arbitrary XML data in a fairly complex
structure.
In instance documents, the element may look like this:
<embeddeddata>just text</embeddeddata>

<embeddeddata>text <x>with</x> elements</embeddeddata>

<embeddeddata><x>element</x><y>structures</y></embeddeddata>

We marshall/unmarshall our data with our own implementations of
XMLFieldDescriptors.
The current solution to marshall/unmarshall the above element is coded like
this:

public class EmbeddedDataDescriptor extends XMLClassDescriptorImpl {
// details left out for simplicity reasons
// ...
  protected void init() {
    XMLFieldDescriptorImpl desc = new ew
XMLFieldDescriptorImpl(Object.class, "data", null, NodeType.Element);
    desc.setMatches("*"); // matches anything inside the embeddeddata
element 
    XMLFieldHandler        handler = (new XMLFieldHandler() {

      public Object getValue(Object obj) {
        m_logger.debug("Calling getValue() of data descriptor. Object =
"+obj);
        
        EmbeddedData ed     = (EmbeddedData)obj;
        // parse the data with the   SAX2ANY helper, pass object of type
AnyNode as value
        StringReader source = null;
        XMLReader    reader = null;
        SAX2ANY      s2a    = null;
        AnyNode      any    = null;
        if ((ed.getData() != null) && !("".equals(ed.getData()))) {
          try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setValidating(false);
            factory.setNamespaceAware(true);
            SAXParser parser = factory.newSAXParser();
            reader = parser.getXMLReader();
            s2a = new SAX2ANY(new Namespaces());
            // create and register content handler
            reader.setContentHandler(s2a);
            // prepare input for parsing
            source = new StringReader("<embeddeddata>" +ed.getData()+
"</embeddeddata>");
            InputSource is = new InputSource(source);            
            reader.setContentHandler(s2a);
            reader.setErrorHandler(s2a);
            reader.setFeature("http://xml.org/sax/features/namespaces";,
true);
 
reader.setFeature("http://xml.org/sax/features/namespace-prefixes";, false);
            reader.parse(is);
            any = s2a.getStartingNode();
            any = any.getFirstChild();
          }
          catch (Exception e) {
            throw new RuntimeException("Exception during getValue() of
embedded data: " + e.getMessage(), e);
          }
          finally {
            if (source != null) {
              source.close();
            }
          }
        }
        return any;
      }

      public void setValue(Object obj, Object value) {
        m_logger.debug("Calling setValue() of data descriptor. Object =
"+obj+", value = "+value);
        
        EmbeddedData ed     = (EmbeddedData)obj;
        AnyNode      node   = (AnyNode)value;
        AnyNode2SAX  ats    = new AnyNode2SAX(node, new Namespaces());
        Serializer   s      = new org.apache.xml.serialize.XMLSerializer();
        OutputFormat format = new OutputFormat();
        format.setMethod(Method.XML);
        format.setPreserveSpace(true);
        format.setIndenting(false);
        format.setOmitXMLDeclaration(true);
        s.setOutputFormat(format);
        StringWriter writer = new StringWriter();
        s.setOutputCharStream(writer);
        try {
          ats.setDocumentHandler(s.asDocumentHandler());
          ats.start();
          writer.flush();
          String strData = writer.toString();
          if (ed.getData() != null) {
            strData = ed.getData() + strData;
          }
          ed.setData(strData);
        }
        catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
        finally {
          try {
            if (writer != null) {
              writer.close();
            }
          }
          catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
          }
        }
      }

      public Object newInstance(Object parent) {
        // left our for simplicity
      };
    });

    desc.setHandler(handler);
    super.addFieldDescriptor(desc);
  }

}

The problems we have with this approach:

1) If we use a XML structure like the last sample
(<embeddeddata><x>element</x><y>structures</y></embeddeddata>),
 only the first element (the x) is marshalled, the y is lost.
This is perhaps it is the returned root node of our getValue() method, but
shouldn't the siblings be handled as well?

2) In the second example (the mixed content), all text content is collected
to one single text node, resulting in the following output:
<embeddeddata>text <x>with</x> elements</embeddeddata>

3) We want not to change the whitespaces that are inserted in the XML
structure, but unfortunately, the SAX2ANY class strips out whitespaces
between elements. Could this be changed somehow?
Example: the following XML fragment
<x>
  <y>bla</y>
</x>

Is stripped down to:
<x><y>bla</y></x>

But we want to keep the original formatting.

Thanks for any hints
Christian



----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-user

Reply via email to