Re: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, Stri
Brought to you by:
niallg
|
From: Niall G. - Y. <Nia...@yi...> - 2012-11-15 22:45:11
|
Sorry, my mistake I should have suggested a converter. Here you can use @Convert annotation like so. @Convert(CarConverter.class) Map<String, String> var; Take a look at the following converters https://simple.svn.sf.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/convert/HideEnclosingConverterTest.java https://simple.svn.sf.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/convert/ExampleConverters.java -----Original Message----- From: Christian Klotz [mailto:c....@sp...] Sent: Friday, 16 November 2012 12:28 AM To: Niall Gallagher - Yieldbroker Cc: sim...@li... Subject: Re: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, String> Hi Niall, thanks for your quick response. Now I have implemented an Visitor. In the read method, I can get a nodeMap with all xml attributes. I can also detect via refection which attributes have the annotation @Attribute. All other attributes should be stored in the HashMap "furtherAttributes". But I don't known how to put them into the HashMap "furtherAttributes". I do not have the resulting car object. Do you have any tip? public class AnyAttributesVisitor implements Visitor { @Override public void read(Type type, NodeMap<InputNode> nodeMap) throws Exception { // nodeMap contains all xml attributes of the car xml // Content is: // {color=attribute color='red', length=attribute length='4.3', // nrOfDoors=attribute nrOfDoors='4', fuelConsumption=attribute // fuelConsumption='7.8', topSpeed=attribute topSpeed='190'} //Detect attributes with Annotation @Attribute ArrayList<String> attributesWithAnnotation = new ArrayList<String>(); for (Field field : type.getType().getFields()) { if (field.getAnnotation(Attribute.class) != null) { String name = field.getAnnotation(Attribute.class).name(); if (name == null || name.equals("")) { name = field.getName(); } attributesWithAnnotation.add(name); } } for (String entry : nodeMap.getNode().getAttributes()) { if (!attributesWithAnnotation.contains(entry)) { String furtherAttributeKey = entry; String furtherAttributeValue = nodeMap.getNode() .getAttribute(entry).getValue(); // TODO: Add Key and Value to the Hashmap furtherAttributes nodeMap.remove(furtherAttributeKey); } } } @Override public void write(Type type, NodeMap<OutputNode> nodeMap) throws Exception { } } This is my test case: public void testCarDeserialisation() throws Exception { String xml = "<Car color=\"red\" length=\"4.3\" nrOfDoors=\"4\" fuelConsumption=\"7.8\" topSpeed=\"190\" />"; Serializer serializer = new Persister(new VisitorStrategy( new AnyAttributesVisitor())); Car car = serializer.read(Car.class, xml); } Thanks Christian Am 15.11.2012 00:33, schrieb Niall Gallagher - Yieldbroker: > I think a Visitor would be simpler than a Strategy, there are many test cases doing this very thing. Just browse through them, I am sure you will find a template. You can browse them here http://simple.svn.sourceforge.net/viewvc/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/ > > -----Original Message----- > From: Christian Klotz [mailto:c....@sp...] > Sent: Wednesday, 14 November 2012 8:26 PM > To: sim...@li... > Subject: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, String> > > Hi SimpleXml Team, > > I use SimpleXml frequently on android and it is great. > > Now I have a question how to do that job: > All XML attributes that are not defined in the Java class with @Attribute should be serialized and deserialized into a HashMap<String,String>. > > Here is an example: > > This is out test class "Car" > > @Root(strict = false, name = "Car") > public class Car > { > @Attribute > public double length; > > @Attribute > public String color; > > @Attribute > public int nrOfDoors; > > public HashMap<String, String> furtherAttributes = new HashMap<String, String>(); } > > And this is the serialization test method: > public void testCar() throws Exception > { > Car car = new Car(); > > car.color = "red"; > car.length = 4.3; > car.nrOfDoors = 4; > > car.furtherAttributes.put("fuelConsumption", "7.8"); > car.furtherAttributes.put("topSpeed", "190"); > > Serializer serializer = new Persister(); > StringWriter stringwriter = new StringWriter(); > serializer.write(car, stringwriter); > > String xml = stringwriter.toString(); > } > > > The result of the serialization is: > <Car color="red" length="4.3" nrOfDoors="4"/> > > So the furtherAttributes of the HashMap are missing. The result should be: > <Car color="red" length="4.3" nrOfDoors="4" fuelConsumption="7.8" > topSpeed="190" /> > > And the way back should also work: > So if we have a xml like this: > <Car color="green" length="3.3" nrOfDoors="2" topSpeed="190" brand="audi" /> After the deserialization the HashMap "furtherAttributes" should have the two undefined attributes "topSpeed" and "brand". > > I already read the mailing list and some SimpleXml test cases. > So I try implement a new Strategy to solve that problem. > > The AnyAttributeRegistryStrategy looks for classes with annotation "AnyClass" and inside that class searches for the annotation "Any". > The annotation "Any" is used to tag the HashMap, where the futher attributes should be serialized to. > > public class AnyAttributeRegistryStrategy extends RegistryStrategy { > public AnyAttributeRegistryStrategy(Registry registry) > { > super(registry); > } > > @Override > public boolean write(Type type, Object value, NodeMap<OutputNode> node, > @SuppressWarnings("rawtypes") Map map) throws Exception > { > > if (value.getClass().getAnnotation(AnyClass.class) != null) > { > for (Field field : value.getClass().getFields()) > { > if (field.getAnnotation(Any.class) != null) > { > Object mapObject = field.get(value); > if (mapObject instanceof Map<?, ?>) > { > Map<?, ?> keyValueMap = (Map<?, ?>) mapObject; > for (Entry<?, ?> keyValuePair : > keyValueMap.entrySet()) > { > if (keyValuePair.getKey() != null > && keyValuePair.getValue() != null) > { > node.getNode().setAttribute( keyValuePair.getKey().toString(), keyValuePair.getValue().toString()); > } > } > > } > } > } > } > > return super.write(type, value, node, map); > } > } > > And this is the Car class with the new annotations: > @AnyClass > @Root(strict = false, name = "Car") > public class Car > { > @Attribute > public double length; > > @Attribute > public String color; > > @Attribute > public int nrOfDoors; > > @Any > public HashMap<String, String> furtherAttributes = new HashMap<String, String>(); } > > Now the serialisation of the class to xml works. > But I do not have a correctly working solution for the deserialisation. > Do you have any ideas? > > Thanks for you help > > Christian Klotz > > > > > > > ------------------------------------------------------------------------------ > Monitor your physical, virtual and cloud infrastructure from a single web console. Get in-depth insight into apps, servers, databases, vmware, SAP, cloud infrastructure, etc. Download 30-day Free Trial. > Pricing starts from $795 for 25 servers or applications! > http://p.sf.net/sfu/zoho_dev2dev_nov > _______________________________________________ > Simple-support mailing list > Sim...@li... > https://lists.sourceforge.net/lists/listinfo/simple-support > -- Mit freundlichen Grüßen / Kind regards Christian Klotz Software Engineer SPEDION GmbH Industriestraße 7 D - 63829 Krombach Fon: +49 (0) 6024 / 50990-132 Fax: +49 (0) 6024 / 50990-121 mailto:c....@sp... SPEDION GmbH - Industriestraße 7 - 63829 Krombach - Germany Amtsgericht Aschaffenburg, HRB 8647 Geschäftsführer: Günter Englert, Wolfram Grohse |