I'm struggling to understanding how I can deserialize the following response from an RSS feed. I need the text blah blah blah
etc as well as the embedded image source http://host/path/to/picture.jpg
.
<description>blah blah blah blah br />
<![CDATA[<img src=http://host/path/to/picture.jpg>]]><br />
blah blah blah blah<br /><br />
</description>
Here's my model class (or rather what I want it to be) - I've shortened it for brevity:
public static class Item {
...
@Element(name="description", required=false)
String descriptionContent;
String imageLink;
...
}
From the docs I know I can set data=true
on the @Element
attribute but from my reading that works if the entire content of your element is CDATA, not partially.
I'm using doing this on Android using Retrofit and the SimpleXMLConverter but I think that is just by the by.
-
Thanks for the downvotes without comment. Helped me a lot!mez.pahlan– mez.pahlan2016年07月23日 12:14:12 +00:00Commented Jul 23, 2016 at 12:14
-
I got the same problem. Do you have any better solution ?Tai Dao– Tai Dao2017年04月10日 10:12:19 +00:00Commented Apr 10, 2017 at 10:12
1 Answer 1
I figured this out eventually. Hopefully this will help others in the future.
What was needed was a way to interrupt the deserialization process and run some custom code to extract the data. SimpleXML allows you to use many different strategies for serialization / deserialization. I chose one called the Annotation Strategy where by I annotate my POJO model class with the @Convert
annotation that points to a converter class.
....
@Element(name="description", required=false)
@Convert(DescriptionConverter.class)
Description description;
...
And here's what the converter looks like:
public class DescriptionConverter implements Converter<RssFeed.Description> {
@Override
public RssFeed.Description read(InputNode node) throws Exception {
final String IMG_SRC_REG_EX = "<img src=([^>]+)>";
final String HTML_TAG_REG_EX = "</?[^>]+>";
String nodeText = node.getValue();
Pattern imageLinkPattern = Pattern.compile(IMG_SRC_REG_EX);
Matcher matcher = imageLinkPattern.matcher(nodeText);
String link = null;
while (matcher.find()) {
link = matcher.group(1);
}
String text = nodeText.replaceFirst(IMG_SRC_REG_EX, "")
.replaceAll(HTML_TAG_REG_EX, "");
return new RssFeed.Description(text, link);
}
@Override
public void write(OutputNode node, RssFeed.Description value) throws Exception {
...
}
}
You still need to tell Simple to use a different strategy though otherwise it will ignore the annotation. Given that I am using Retrofit and the SimpleXMLConverter here is what my implemenation looks like:
private static final Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy())));
-
1your solution is not wrong, but I found more universal solution: stackoverflow.com/a/34493919/1537413Dika– Dika2018年04月16日 22:33:23 +00:00Commented Apr 16, 2018 at 22:33