Hi Johann,

sorry for the late response, but I was on holidays and try to clear the 
backlog slowly again.

Johann Kerdal wrote:

> Hi guys,
> 
> I need to unmarshall an XML document to a
> linkedHashMap<String,ColumnAttributes>
> 
> The XML document I get from the server system is containing the list of
> objects:
> <ColumnAttributes key="BSI_REFIN_INTR_BU_CURRY_AMT">
>       <name>BSI_REFIN_INTR_BU_CURRY_AMT</name>
>       <label>Refinancing interest amount in BU currency</label>
>       <length>8.0</length>
>       <format>NLNUM18.</format>
>       <inFormat>NLNUM18.</inFormat>
>   </ColumnAttributes>
> 
> As you can see, the key is an attribute of the ColumnAttributes Element.
> 
> I have tested this code:
> new NamedMapConverter(LinkedHashMap.class,xstream.getMapper(),
> "column", "key", String.class, *"column"*, ColumnAttributes.class, true,
> false, xstream.getConverterLookup())
> 
> but it generates one element for the key and one for the value.
> 
> If I use this one:
> new NamedMapConverter(LinkedHashMap.class,xstream.getMapper(),
> "column", "key", String.class, *null*, ColumnAttributes.class, true,
> false, xstream.getConverterLookup())
> 
> Here is the complete code:
> XStream xstream = new XStream(new DomDriver());
>         // XStream xstream = new XStream(new DomDriver());
>         xstream.alias("columns",LinkedHashMap.class) ;
>         xstream.alias("column",ColumnAttributes.class) ;
>         ConverterLookup lookup = xstream.getConverterLookup() ;
>         Converter conv =
> xstream.getConverterLookup().lookupConverterForType(String.class) ;
>         System.out.println(conv.canConvert(String.class)) ;
>         xstream.registerConverter(
>          new NamedMapConverter(LinkedHashMap.class,xstream.getMapper(),
> "column", "key", String.class, null, ColumnAttributes.class, true, false,
> xstream.getConverterLookup()
>         ));
>         // String xml = xstream.toXML(rulesBook.getColumnsAttributes());
>         // System.out.println(xml);
>         String xml="<columns><column
> 
key=\"BSI_REFIN_INTR_BU_CURRY_AMT\"><name>BSI_REFIN_INTR_BU_CURRY_AMT</name><label>Refinancing
> interest amount in BU
> currency</label><length>8.0</length></column></columns>" ;
>         LinkedHashMap<String,ColumnAttributes> test =
> (LinkedHashMap<String,ColumnAttributes>)xstream.fromXML(xml) ;
> 

[snip]

> 
> 
> Is it possible to have the key as an attribute of the value element in the
> XML using the NamedMapconverter?

No. See, a map has normally following XML representation:

 <map>
  <entry>
    <key>K</key>
    <value>V</value>
  </entry>
 </map>

where K and/or V might either be a String or another XML structure. The 
NamedMapConverter allows you to use different names for the inner elements 
entry, key and value.

A special mode is offered to drop the entry element:

 <map>
  <key>K</key>
  <value>V</value>
 </map>

Or you might use attributes for key and/or value *if* K resp. V is a String 
i.e. the converter for those objects returns a single value. However, then 
you have to keep the entry element:

 <map>
  <entry key="K">
    <value>V</value>
  </entry>
 </map>

or:

 <map>
  <entry key="K" value="V"/>
 </map>

Nevertheless, the representation for key and value is always present either 
as XML element or attribute.

Since your value type contains the key, you try to drop the key element of 
the map and use the value as entry element instead with an attribute for the 
key property. Obviously your situation does not match the functionality of 
this converter.

> If not, do you have any suggestion for me?
> 
> Any feedback is welcome..

I would actually just use a custom converter for the LinkedHashMap (register 
locally if the LinkedHashMap is an element of a higher level, otherwise all 
LinkedHashMaps will be handled):

================== %< =======================
 class AttributesConverter implements Converter {
   Converter listConverter;
   AttributesConverter(Mapper mapper) {
     listConverter = new CollectionConverter(mapper);
   }
   boolean canConvert(Class t) {
     return LinkedHashMap.class.equals(t);
   }
   void marshal(Object source, HierarchicalStreamWriter writer, 
MarshallingContext context) {
     Map map = (Map)source;
     listConverter.marshal(map.values(), writer, context);
   }
   Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext 
context) {
     Collection<ColumnAttributes> values =
       listConverter.unmarshal(reader, context);
     Map<String, ColumnAttributes> map = new LinkedHashMap<>();
     for(ColumnAttributes attr : values) {
       map.put(attr.getKey(), attr);
     }
     return map;
   }
 }
 xstream.registerConverter(
   new AttributesConverter(xstream.getMapper()));
 xstream.useAttributeFor(ColumnAttributes.class, "key");
 xstream.alias("ColumnAttributes", ColumnAttributes.class);
================== %< =======================

Hope this helps,
Jörg



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to